@expressots/studio-agent 4.0.0-preview.1 → 4.0.0-preview.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -143
- package/dist/agent.d.ts +75 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +443 -14
- package/dist/agent.js.map +1 -1
- package/dist/discovery/route-scanner.d.ts +62 -1
- package/dist/discovery/route-scanner.d.ts.map +1 -1
- package/dist/discovery/route-scanner.js +923 -101
- package/dist/discovery/route-scanner.js.map +1 -1
- package/dist/identity/index.d.ts +2 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +2 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/install-id.d.ts +22 -0
- package/dist/identity/install-id.d.ts.map +1 -0
- package/dist/identity/install-id.js +73 -0
- package/dist/identity/install-id.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/instrumentation/tracer.d.ts.map +1 -1
- package/dist/instrumentation/tracer.js +40 -4
- package/dist/instrumentation/tracer.js.map +1 -1
- package/dist/introspection/database-introspector.d.ts +58 -0
- package/dist/introspection/database-introspector.d.ts.map +1 -0
- package/dist/introspection/database-introspector.js +351 -0
- package/dist/introspection/database-introspector.js.map +1 -0
- package/dist/logging/log-capture.d.ts.map +1 -1
- package/dist/logging/log-capture.js +23 -1
- package/dist/logging/log-capture.js.map +1 -1
- package/dist/recording/request-recorder.js +73 -73
- package/dist/security/posture-analyzer.d.ts.map +1 -1
- package/dist/security/posture-analyzer.js +1 -1
- package/dist/security/posture-analyzer.js.map +1 -1
- package/dist/types/index.d.ts +261 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/package.json +18 -15
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Introspector
|
|
3
|
+
*
|
|
4
|
+
* Builds a read-only snapshot of the ExpressoTS in-memory database
|
|
5
|
+
* (`InMemoryDBProvider`) for the Studio "Database" view: entity schemas
|
|
6
|
+
* (fields, relations, indexes), per-table record counts, and paginated
|
|
7
|
+
* row data.
|
|
8
|
+
*
|
|
9
|
+
* Designed to fail gracefully: if no `InMemoryDBProvider` is registered,
|
|
10
|
+
* if the container isn't the expected Inversify shape, or if the provider
|
|
11
|
+
* doesn't expose the expected API, every method returns an "unavailable"
|
|
12
|
+
* result instead of throwing. The agent never imports `@expressots/core`
|
|
13
|
+
* directly — the provider is duck-typed so the agent stays decoupled.
|
|
14
|
+
*/
|
|
15
|
+
/** Reflect metadata keys used by the in-memory DB schema decorators. */
|
|
16
|
+
const DB_METADATA_KEYS = {
|
|
17
|
+
entity: 'expressots:db:entity',
|
|
18
|
+
primaryKey: 'expressots:db:primaryKey',
|
|
19
|
+
index: 'expressots:db:index',
|
|
20
|
+
unique: 'expressots:db:unique',
|
|
21
|
+
autoGenerate: 'expressots:db:autoGenerate',
|
|
22
|
+
default: 'expressots:db:default',
|
|
23
|
+
relation: 'expressots:db:relation',
|
|
24
|
+
nullable: 'expressots:db:nullable',
|
|
25
|
+
};
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
const ReflectAny = Reflect;
|
|
28
|
+
const FIELD_SAMPLE_SIZE = 50;
|
|
29
|
+
export class DatabaseIntrospector {
|
|
30
|
+
appContainer;
|
|
31
|
+
provider = null;
|
|
32
|
+
resolved = false;
|
|
33
|
+
constructor(appContainer) {
|
|
34
|
+
this.appContainer = appContainer;
|
|
35
|
+
}
|
|
36
|
+
/** Whether an InMemoryDBProvider could be resolved from the container. */
|
|
37
|
+
isAvailable() {
|
|
38
|
+
return this.getProvider() !== null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build a schema snapshot of every table in the in-memory database.
|
|
42
|
+
* Returns `{ available: false }` when no provider is registered.
|
|
43
|
+
*/
|
|
44
|
+
capture() {
|
|
45
|
+
const provider = this.getProvider();
|
|
46
|
+
if (!provider)
|
|
47
|
+
return this.emptySnapshot();
|
|
48
|
+
try {
|
|
49
|
+
const db = provider.getDatabase?.();
|
|
50
|
+
const tables = db?.tables;
|
|
51
|
+
const entities = [];
|
|
52
|
+
let totalRecords = 0;
|
|
53
|
+
if (tables && typeof tables.forEach === 'function') {
|
|
54
|
+
for (const [name, adapter] of tables) {
|
|
55
|
+
const entity = this.buildEntitySchema(name, adapter);
|
|
56
|
+
entities.push(entity);
|
|
57
|
+
totalRecords += entity.recordCount;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
available: true,
|
|
62
|
+
tableCount: entities.length,
|
|
63
|
+
totalRecords,
|
|
64
|
+
entities,
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return this.emptySnapshot();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Return a page of rows from a single table.
|
|
74
|
+
* Returns an empty page when the provider or table is unavailable.
|
|
75
|
+
*/
|
|
76
|
+
async getTableData(table, offset = 0, limit = 50) {
|
|
77
|
+
const empty = {
|
|
78
|
+
table,
|
|
79
|
+
rows: [],
|
|
80
|
+
total: 0,
|
|
81
|
+
offset,
|
|
82
|
+
limit,
|
|
83
|
+
};
|
|
84
|
+
const provider = this.getProvider();
|
|
85
|
+
if (!provider)
|
|
86
|
+
return empty;
|
|
87
|
+
try {
|
|
88
|
+
const adapter = provider.table?.(table);
|
|
89
|
+
if (!adapter)
|
|
90
|
+
return empty;
|
|
91
|
+
const total = await adapter.count();
|
|
92
|
+
const rows = await adapter.findMany({
|
|
93
|
+
skip: offset,
|
|
94
|
+
take: limit,
|
|
95
|
+
});
|
|
96
|
+
return { table, rows, total, offset, limit };
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return empty;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
103
|
+
// Internals
|
|
104
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
105
|
+
/** Resolve and cache the InMemoryDBProvider instance from the container. */
|
|
106
|
+
getProvider() {
|
|
107
|
+
if (this.resolved)
|
|
108
|
+
return this.provider;
|
|
109
|
+
this.resolved = true;
|
|
110
|
+
const inversify = this.getInversifyContainer();
|
|
111
|
+
if (!inversify) {
|
|
112
|
+
this.provider = null;
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const dict = inversify._bindingDictionary;
|
|
117
|
+
const map = dict?._map;
|
|
118
|
+
if (!map) {
|
|
119
|
+
this.provider = null;
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
for (const [sid, bindings] of map) {
|
|
123
|
+
// Match on the service identifier name as well as the
|
|
124
|
+
// implementationType. Dynamic-value / factory / constant bindings
|
|
125
|
+
// (`bind(P).toDynamicValue(...)`) carry no `implementationType`, so
|
|
126
|
+
// matching only on it would miss those registrations — the service
|
|
127
|
+
// identifier (the provider class) is the reliable signal.
|
|
128
|
+
const sidName = this.identifierName(sid);
|
|
129
|
+
for (const binding of bindings) {
|
|
130
|
+
const implName = binding?.implementationType?.name;
|
|
131
|
+
if (sidName === 'InMemoryDBProvider' ||
|
|
132
|
+
implName === 'InMemoryDBProvider') {
|
|
133
|
+
const instance = this.tryResolve(inversify, sid);
|
|
134
|
+
if (this.looksLikeProvider(instance)) {
|
|
135
|
+
this.provider = instance;
|
|
136
|
+
return this.provider;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// fall through to null
|
|
144
|
+
}
|
|
145
|
+
this.provider = null;
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
/** Best-effort container resolution that never throws. */
|
|
149
|
+
tryResolve(inversify, sid) {
|
|
150
|
+
try {
|
|
151
|
+
return inversify.get(sid);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Readable name for a service identifier (class, string, or symbol). */
|
|
158
|
+
identifierName(sid) {
|
|
159
|
+
if (typeof sid === 'function')
|
|
160
|
+
return sid.name ?? '';
|
|
161
|
+
if (typeof sid === 'string')
|
|
162
|
+
return sid;
|
|
163
|
+
if (typeof sid === 'symbol')
|
|
164
|
+
return sid.description ?? sid.toString();
|
|
165
|
+
return '';
|
|
166
|
+
}
|
|
167
|
+
/** Duck-type check for the InMemoryDBProvider public API. */
|
|
168
|
+
looksLikeProvider(candidate) {
|
|
169
|
+
if (!candidate || typeof candidate !== 'object')
|
|
170
|
+
return false;
|
|
171
|
+
const obj = candidate;
|
|
172
|
+
return (typeof obj.getDatabase === 'function' &&
|
|
173
|
+
typeof obj.getStats === 'function' &&
|
|
174
|
+
typeof obj.table === 'function');
|
|
175
|
+
}
|
|
176
|
+
getInversifyContainer() {
|
|
177
|
+
if (!this.appContainer)
|
|
178
|
+
return null;
|
|
179
|
+
const inv = this.appContainer.Container ??
|
|
180
|
+
this.appContainer.container ??
|
|
181
|
+
this.appContainer;
|
|
182
|
+
if (!inv)
|
|
183
|
+
return null;
|
|
184
|
+
if (!inv._bindingDictionary)
|
|
185
|
+
return null;
|
|
186
|
+
return inv;
|
|
187
|
+
}
|
|
188
|
+
/** Build the schema for a single table from its adapter + entity metadata. */
|
|
189
|
+
buildEntitySchema(name, adapter) {
|
|
190
|
+
const stats = this.safeStats(adapter);
|
|
191
|
+
const entityClass = adapter?.entityClass;
|
|
192
|
+
const fields = this.buildFields(entityClass, adapter, stats.indexes);
|
|
193
|
+
const relations = this.buildRelations(entityClass);
|
|
194
|
+
let timestamps = true;
|
|
195
|
+
let softDelete = false;
|
|
196
|
+
if (entityClass) {
|
|
197
|
+
const meta = ReflectAny.getMetadata?.(DB_METADATA_KEYS.entity, entityClass);
|
|
198
|
+
if (meta) {
|
|
199
|
+
timestamps = Boolean(meta.timestamps);
|
|
200
|
+
softDelete = Boolean(meta.softDelete);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
name,
|
|
205
|
+
timestamps,
|
|
206
|
+
softDelete,
|
|
207
|
+
fields,
|
|
208
|
+
relations,
|
|
209
|
+
recordCount: stats.recordCount,
|
|
210
|
+
indexes: stats.indexes,
|
|
211
|
+
memoryEstimate: stats.memoryEstimate,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
safeStats(adapter) {
|
|
215
|
+
try {
|
|
216
|
+
const stats = adapter?.getStats?.();
|
|
217
|
+
if (stats) {
|
|
218
|
+
return {
|
|
219
|
+
recordCount: Number(stats.recordCount) || 0,
|
|
220
|
+
indexes: Array.isArray(stats.indexes) ? stats.indexes : [],
|
|
221
|
+
memoryEstimate: Number(stats.memoryEstimate) || 0,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// ignore
|
|
227
|
+
}
|
|
228
|
+
return { recordCount: 0, indexes: [], memoryEstimate: 0 };
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Build the field list. Prefers decorator metadata, then supplements with
|
|
232
|
+
* keys discovered by sampling stored rows (so undecorated fields appear).
|
|
233
|
+
*/
|
|
234
|
+
buildFields(entityClass, adapter, indexes) {
|
|
235
|
+
const primaryKeys = new Set();
|
|
236
|
+
const uniqueFields = new Set();
|
|
237
|
+
const indexedFields = new Set();
|
|
238
|
+
const nullableFields = new Set();
|
|
239
|
+
const autoGenerate = {};
|
|
240
|
+
for (const idx of indexes) {
|
|
241
|
+
indexedFields.add(idx.field);
|
|
242
|
+
if (idx.unique)
|
|
243
|
+
uniqueFields.add(idx.field);
|
|
244
|
+
}
|
|
245
|
+
if (entityClass) {
|
|
246
|
+
for (const pk of this.metaArray(entityClass, DB_METADATA_KEYS.primaryKey)) {
|
|
247
|
+
primaryKeys.add(String(pk));
|
|
248
|
+
}
|
|
249
|
+
for (const u of this.metaArray(entityClass, DB_METADATA_KEYS.unique)) {
|
|
250
|
+
uniqueFields.add(String(u));
|
|
251
|
+
}
|
|
252
|
+
for (const n of this.metaArray(entityClass, DB_METADATA_KEYS.nullable)) {
|
|
253
|
+
nullableFields.add(String(n));
|
|
254
|
+
}
|
|
255
|
+
for (const idx of this.metaArray(entityClass, DB_METADATA_KEYS.index)) {
|
|
256
|
+
if (idx && idx.field)
|
|
257
|
+
indexedFields.add(String(idx.field));
|
|
258
|
+
}
|
|
259
|
+
const auto = ReflectAny.getMetadata?.(DB_METADATA_KEYS.autoGenerate, entityClass) ||
|
|
260
|
+
{};
|
|
261
|
+
for (const [field, strategy] of Object.entries(auto)) {
|
|
262
|
+
autoGenerate[field] = String(strategy);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Discover field names: decorated fields + sampled row keys.
|
|
266
|
+
const fieldNames = new Set([
|
|
267
|
+
...primaryKeys,
|
|
268
|
+
...uniqueFields,
|
|
269
|
+
...indexedFields,
|
|
270
|
+
...nullableFields,
|
|
271
|
+
...Object.keys(autoGenerate),
|
|
272
|
+
]);
|
|
273
|
+
for (const key of this.sampleRowKeys(adapter)) {
|
|
274
|
+
fieldNames.add(key);
|
|
275
|
+
}
|
|
276
|
+
// Ensure id is always present and ordered first.
|
|
277
|
+
fieldNames.add('id');
|
|
278
|
+
const ordered = ['id', ...[...fieldNames].filter((f) => f !== 'id').sort()];
|
|
279
|
+
return ordered.map((field) => ({
|
|
280
|
+
name: field,
|
|
281
|
+
isPrimaryKey: primaryKeys.has(field) || field === 'id',
|
|
282
|
+
isUnique: uniqueFields.has(field),
|
|
283
|
+
isIndexed: indexedFields.has(field),
|
|
284
|
+
isNullable: nullableFields.has(field),
|
|
285
|
+
autoGenerate: autoGenerate[field],
|
|
286
|
+
}));
|
|
287
|
+
}
|
|
288
|
+
buildRelations(entityClass) {
|
|
289
|
+
if (!entityClass)
|
|
290
|
+
return [];
|
|
291
|
+
const relations = this.metaArray(entityClass, DB_METADATA_KEYS.relation);
|
|
292
|
+
return relations.map((rel) => ({
|
|
293
|
+
field: String(rel.field),
|
|
294
|
+
type: rel.type,
|
|
295
|
+
target: this.resolveTargetName(rel.target),
|
|
296
|
+
foreignKey: rel.foreignKey || undefined,
|
|
297
|
+
through: rel.through || undefined,
|
|
298
|
+
}));
|
|
299
|
+
}
|
|
300
|
+
/** Resolve a relation target factory `() => Class` to a readable name. */
|
|
301
|
+
resolveTargetName(targetFactory) {
|
|
302
|
+
try {
|
|
303
|
+
if (typeof targetFactory === 'function') {
|
|
304
|
+
const target = targetFactory();
|
|
305
|
+
if (target) {
|
|
306
|
+
const meta = ReflectAny.getMetadata?.(DB_METADATA_KEYS.entity, target);
|
|
307
|
+
if (meta?.name)
|
|
308
|
+
return String(meta.name);
|
|
309
|
+
if (target.name)
|
|
310
|
+
return String(target.name);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
// ignore
|
|
316
|
+
}
|
|
317
|
+
return 'unknown';
|
|
318
|
+
}
|
|
319
|
+
/** Sample stored row keys synchronously via the adapter's MemoryStore. */
|
|
320
|
+
sampleRowKeys(adapter) {
|
|
321
|
+
try {
|
|
322
|
+
const store = adapter?.store;
|
|
323
|
+
const rows = typeof store?.findAll === 'function' ? store.findAll() : [];
|
|
324
|
+
const keys = new Set();
|
|
325
|
+
for (const row of rows.slice(0, FIELD_SAMPLE_SIZE)) {
|
|
326
|
+
if (row && typeof row === 'object') {
|
|
327
|
+
for (const key of Object.keys(row))
|
|
328
|
+
keys.add(key);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return [...keys];
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
metaArray(target, key) {
|
|
338
|
+
const value = ReflectAny.getMetadata?.(key, target);
|
|
339
|
+
return Array.isArray(value) ? value : [];
|
|
340
|
+
}
|
|
341
|
+
emptySnapshot() {
|
|
342
|
+
return {
|
|
343
|
+
available: false,
|
|
344
|
+
tableCount: 0,
|
|
345
|
+
totalRecords: 0,
|
|
346
|
+
entities: [],
|
|
347
|
+
timestamp: new Date().toISOString(),
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=database-introspector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-introspector.js","sourceRoot":"","sources":["../../src/introspection/database-introspector.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-capture.d.ts","sourceRoot":"","sources":["../../src/logging/log-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAcD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqD;IAC7E,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,SAAO;IAI5B;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAqDf,yEAAyE;IACzE,SAAS,IAAI,IAAI;IAiBjB;;;OAGG;IACH,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAI3C,qEAAqE;IACrE,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI;IAKtD,4DAA4D;IAC5D,SAAS,IAAI,QAAQ,EAAE;IAIvB,kCAAkC;IAClC,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,SAAS;
|
|
1
|
+
{"version":3,"file":"log-capture.d.ts","sourceRoot":"","sources":["../../src/logging/log-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAcD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqD;IAC7E,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,SAAO;IAI5B;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAqDf,yEAAyE;IACzE,SAAS,IAAI,IAAI;IAiBjB;;;OAGG;IACH,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAI3C,qEAAqE;IACrE,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI;IAKtD,4DAA4D;IAC5D,SAAS,IAAI,QAAQ,EAAE;IAIvB,kCAAkC;IAClC,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,SAAS;CA4BlB"}
|
|
@@ -136,7 +136,12 @@ export class LogCapture {
|
|
|
136
136
|
const ctx = requestContext.getStore();
|
|
137
137
|
const entry = {
|
|
138
138
|
level,
|
|
139
|
-
|
|
139
|
+
// Strip ANSI escape codes so Studio's web UI (and downstream
|
|
140
|
+
// consumers like cloud log aggregators) don't render raw "[32m…[0m"
|
|
141
|
+
// garbage. The terminal still sees the colored output because the
|
|
142
|
+
// wrapper invokes the original `console[level]` with the untouched
|
|
143
|
+
// args before this hook fires.
|
|
144
|
+
message: stripAnsi(formatArgs(args)),
|
|
140
145
|
timestamp: Date.now(),
|
|
141
146
|
traceId: ctx?.traceId,
|
|
142
147
|
};
|
|
@@ -181,4 +186,21 @@ function formatArgs(args) {
|
|
|
181
186
|
}
|
|
182
187
|
return parts.join(' ');
|
|
183
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Remove ANSI escape sequences (SGR colors, cursor moves, etc.) from a
|
|
191
|
+
* string so it renders cleanly in non-terminal consumers. Targets CSI
|
|
192
|
+
* sequences of the form `ESC [ <params> <final>` which covers
|
|
193
|
+
* essentially all colored-log output in practice.
|
|
194
|
+
*
|
|
195
|
+
* Implemented inline to avoid pulling in the `strip-ansi` dependency.
|
|
196
|
+
*/
|
|
197
|
+
function stripAnsi(input) {
|
|
198
|
+
if (!input)
|
|
199
|
+
return input;
|
|
200
|
+
// Quick check to skip the regex pass when no escape char is present.
|
|
201
|
+
if (input.indexOf('\u001b') === -1)
|
|
202
|
+
return input;
|
|
203
|
+
// eslint-disable-next-line no-control-regex
|
|
204
|
+
return input.replace(/\u001b\[[\d;?]*[ -/]*[@-~]/g, '');
|
|
205
|
+
}
|
|
184
206
|
//# sourceMappingURL=log-capture.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-capture.js","sourceRoot":"","sources":["../../src/logging/log-capture.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"log-capture.js","sourceRoot":"","sources":["../../src/logging/log-capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,45 +27,45 @@ export class RequestRecorder {
|
|
|
27
27
|
this.db = new Database(this.dbPath);
|
|
28
28
|
this.db.pragma('journal_mode = WAL');
|
|
29
29
|
// Create tables
|
|
30
|
-
this.db.exec(`
|
|
31
|
-
CREATE TABLE IF NOT EXISTS requests (
|
|
32
|
-
id TEXT PRIMARY KEY,
|
|
33
|
-
trace_id TEXT,
|
|
34
|
-
timestamp INTEGER NOT NULL,
|
|
35
|
-
method TEXT NOT NULL,
|
|
36
|
-
path TEXT NOT NULL,
|
|
37
|
-
url TEXT NOT NULL,
|
|
38
|
-
headers TEXT NOT NULL,
|
|
39
|
-
query TEXT NOT NULL,
|
|
40
|
-
body TEXT,
|
|
41
|
-
cookies TEXT
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
CREATE TABLE IF NOT EXISTS responses (
|
|
45
|
-
id TEXT PRIMARY KEY,
|
|
46
|
-
request_id TEXT NOT NULL,
|
|
47
|
-
trace_id TEXT,
|
|
48
|
-
timestamp INTEGER NOT NULL,
|
|
49
|
-
status_code INTEGER NOT NULL,
|
|
50
|
-
status_message TEXT NOT NULL,
|
|
51
|
-
headers TEXT NOT NULL,
|
|
52
|
-
body TEXT,
|
|
53
|
-
duration INTEGER NOT NULL,
|
|
54
|
-
FOREIGN KEY (request_id) REFERENCES requests(id) ON DELETE CASCADE
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
CREATE TABLE IF NOT EXISTS traces (
|
|
58
|
-
trace_id TEXT PRIMARY KEY,
|
|
59
|
-
request_id TEXT,
|
|
60
|
-
data TEXT NOT NULL,
|
|
61
|
-
timestamp INTEGER NOT NULL,
|
|
62
|
-
FOREIGN KEY (request_id) REFERENCES requests(id) ON DELETE CASCADE
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
CREATE INDEX IF NOT EXISTS idx_requests_timestamp ON requests(timestamp);
|
|
66
|
-
CREATE INDEX IF NOT EXISTS idx_requests_trace_id ON requests(trace_id);
|
|
67
|
-
CREATE INDEX IF NOT EXISTS idx_requests_path ON requests(path);
|
|
68
|
-
CREATE INDEX IF NOT EXISTS idx_responses_request_id ON responses(request_id);
|
|
30
|
+
this.db.exec(`
|
|
31
|
+
CREATE TABLE IF NOT EXISTS requests (
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
trace_id TEXT,
|
|
34
|
+
timestamp INTEGER NOT NULL,
|
|
35
|
+
method TEXT NOT NULL,
|
|
36
|
+
path TEXT NOT NULL,
|
|
37
|
+
url TEXT NOT NULL,
|
|
38
|
+
headers TEXT NOT NULL,
|
|
39
|
+
query TEXT NOT NULL,
|
|
40
|
+
body TEXT,
|
|
41
|
+
cookies TEXT
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE TABLE IF NOT EXISTS responses (
|
|
45
|
+
id TEXT PRIMARY KEY,
|
|
46
|
+
request_id TEXT NOT NULL,
|
|
47
|
+
trace_id TEXT,
|
|
48
|
+
timestamp INTEGER NOT NULL,
|
|
49
|
+
status_code INTEGER NOT NULL,
|
|
50
|
+
status_message TEXT NOT NULL,
|
|
51
|
+
headers TEXT NOT NULL,
|
|
52
|
+
body TEXT,
|
|
53
|
+
duration INTEGER NOT NULL,
|
|
54
|
+
FOREIGN KEY (request_id) REFERENCES requests(id) ON DELETE CASCADE
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
CREATE TABLE IF NOT EXISTS traces (
|
|
58
|
+
trace_id TEXT PRIMARY KEY,
|
|
59
|
+
request_id TEXT,
|
|
60
|
+
data TEXT NOT NULL,
|
|
61
|
+
timestamp INTEGER NOT NULL,
|
|
62
|
+
FOREIGN KEY (request_id) REFERENCES requests(id) ON DELETE CASCADE
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_requests_timestamp ON requests(timestamp);
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_requests_trace_id ON requests(trace_id);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_requests_path ON requests(path);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_responses_request_id ON responses(request_id);
|
|
69
69
|
`);
|
|
70
70
|
this.initialized = true;
|
|
71
71
|
}
|
|
@@ -87,9 +87,9 @@ export class RequestRecorder {
|
|
|
87
87
|
body,
|
|
88
88
|
cookies,
|
|
89
89
|
};
|
|
90
|
-
const stmt = this.db.prepare(`
|
|
91
|
-
INSERT INTO requests (id, trace_id, timestamp, method, path, url, headers, query, body, cookies)
|
|
92
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
90
|
+
const stmt = this.db.prepare(`
|
|
91
|
+
INSERT INTO requests (id, trace_id, timestamp, method, path, url, headers, query, body, cookies)
|
|
92
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
93
93
|
`);
|
|
94
94
|
stmt.run(id, traceId || null, timestamp, method, path, url, JSON.stringify(headers), JSON.stringify(query), body ? JSON.stringify(body) : null, cookies ? JSON.stringify(cookies) : null);
|
|
95
95
|
// Cleanup old entries if needed
|
|
@@ -113,9 +113,9 @@ export class RequestRecorder {
|
|
|
113
113
|
body,
|
|
114
114
|
duration: duration || 0,
|
|
115
115
|
};
|
|
116
|
-
const stmt = this.db.prepare(`
|
|
117
|
-
INSERT INTO responses (id, request_id, trace_id, timestamp, status_code, status_message, headers, body, duration)
|
|
118
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
116
|
+
const stmt = this.db.prepare(`
|
|
117
|
+
INSERT INTO responses (id, request_id, trace_id, timestamp, status_code, status_message, headers, body, duration)
|
|
118
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
119
119
|
`);
|
|
120
120
|
stmt.run(id, requestId, traceId || null, timestamp, statusCode, statusMessage, JSON.stringify(headers), body ? JSON.stringify(body) : null, duration || 0);
|
|
121
121
|
return response;
|
|
@@ -124,9 +124,9 @@ export class RequestRecorder {
|
|
|
124
124
|
recordTrace(traceId, trace, requestId) {
|
|
125
125
|
if (!this.db)
|
|
126
126
|
throw new Error('RequestRecorder not initialized');
|
|
127
|
-
const stmt = this.db.prepare(`
|
|
128
|
-
INSERT OR REPLACE INTO traces (trace_id, request_id, data, timestamp)
|
|
129
|
-
VALUES (?, ?, ?, ?)
|
|
127
|
+
const stmt = this.db.prepare(`
|
|
128
|
+
INSERT OR REPLACE INTO traces (trace_id, request_id, data, timestamp)
|
|
129
|
+
VALUES (?, ?, ?, ?)
|
|
130
130
|
`);
|
|
131
131
|
stmt.run(traceId, requestId || null, JSON.stringify(trace), Date.now());
|
|
132
132
|
}
|
|
@@ -185,17 +185,17 @@ export class RequestRecorder {
|
|
|
185
185
|
getRecentExchanges(limit = 100, offset = 0) {
|
|
186
186
|
if (!this.db)
|
|
187
187
|
throw new Error('RequestRecorder not initialized');
|
|
188
|
-
const stmt = this.db.prepare(`
|
|
189
|
-
SELECT r.*,
|
|
190
|
-
res.id as res_id, res.timestamp as res_timestamp,
|
|
191
|
-
res.status_code, res.status_message,
|
|
192
|
-
res.headers as res_headers, res.body as res_body, res.duration,
|
|
193
|
-
t.data as trace_data
|
|
194
|
-
FROM requests r
|
|
195
|
-
LEFT JOIN responses res ON r.id = res.request_id
|
|
196
|
-
LEFT JOIN traces t ON r.trace_id = t.trace_id
|
|
197
|
-
ORDER BY r.timestamp DESC
|
|
198
|
-
LIMIT ? OFFSET ?
|
|
188
|
+
const stmt = this.db.prepare(`
|
|
189
|
+
SELECT r.*,
|
|
190
|
+
res.id as res_id, res.timestamp as res_timestamp,
|
|
191
|
+
res.status_code, res.status_message,
|
|
192
|
+
res.headers as res_headers, res.body as res_body, res.duration,
|
|
193
|
+
t.data as trace_data
|
|
194
|
+
FROM requests r
|
|
195
|
+
LEFT JOIN responses res ON r.id = res.request_id
|
|
196
|
+
LEFT JOIN traces t ON r.trace_id = t.trace_id
|
|
197
|
+
ORDER BY r.timestamp DESC
|
|
198
|
+
LIMIT ? OFFSET ?
|
|
199
199
|
`);
|
|
200
200
|
const rows = stmt.all(limit, offset);
|
|
201
201
|
return rows.map((row) => ({
|
|
@@ -241,16 +241,16 @@ export class RequestRecorder {
|
|
|
241
241
|
searchExchanges(query, method, limit = 100) {
|
|
242
242
|
if (!this.db)
|
|
243
243
|
throw new Error('RequestRecorder not initialized');
|
|
244
|
-
let sql = `
|
|
245
|
-
SELECT r.*,
|
|
246
|
-
res.id as res_id, res.timestamp as res_timestamp,
|
|
247
|
-
res.status_code, res.status_message,
|
|
248
|
-
res.headers as res_headers, res.body as res_body, res.duration,
|
|
249
|
-
t.data as trace_data
|
|
250
|
-
FROM requests r
|
|
251
|
-
LEFT JOIN responses res ON r.id = res.request_id
|
|
252
|
-
LEFT JOIN traces t ON r.trace_id = t.trace_id
|
|
253
|
-
WHERE r.path LIKE ?
|
|
244
|
+
let sql = `
|
|
245
|
+
SELECT r.*,
|
|
246
|
+
res.id as res_id, res.timestamp as res_timestamp,
|
|
247
|
+
res.status_code, res.status_message,
|
|
248
|
+
res.headers as res_headers, res.body as res_body, res.duration,
|
|
249
|
+
t.data as trace_data
|
|
250
|
+
FROM requests r
|
|
251
|
+
LEFT JOIN responses res ON r.id = res.request_id
|
|
252
|
+
LEFT JOIN traces t ON r.trace_id = t.trace_id
|
|
253
|
+
WHERE r.path LIKE ?
|
|
254
254
|
`;
|
|
255
255
|
const params = [`%${query}%`];
|
|
256
256
|
if (method) {
|
|
@@ -353,10 +353,10 @@ export class RequestRecorder {
|
|
|
353
353
|
const row = countStmt.get();
|
|
354
354
|
if (row.count > this.maxExchanges) {
|
|
355
355
|
const deleteCount = row.count - this.maxExchanges;
|
|
356
|
-
const deleteStmt = this.db.prepare(`
|
|
357
|
-
DELETE FROM requests WHERE id IN (
|
|
358
|
-
SELECT id FROM requests ORDER BY timestamp ASC LIMIT ?
|
|
359
|
-
)
|
|
356
|
+
const deleteStmt = this.db.prepare(`
|
|
357
|
+
DELETE FROM requests WHERE id IN (
|
|
358
|
+
SELECT id FROM requests ORDER BY timestamp ASC LIMIT ?
|
|
359
|
+
)
|
|
360
360
|
`);
|
|
361
361
|
deleteStmt.run(deleteCount);
|
|
362
362
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posture-analyzer.d.ts","sourceRoot":"","sources":["../../src/security/posture-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,YAAY,EAEZ,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,SAAS,EAEV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAG1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,SAAS,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,EAAE,CAWrE;
|
|
1
|
+
{"version":3,"file":"posture-analyzer.d.ts","sourceRoot":"","sources":["../../src/security/posture-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,YAAY,EAEZ,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,SAAS,EAEV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAG1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,SAAS,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,EAAE,CAWrE;AA8ZD,YAAY,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -137,7 +137,7 @@ function checkAuthGaps(input) {
|
|
|
137
137
|
const out = [];
|
|
138
138
|
const lastByRoute = mostRecentSuccessByRoute(input.exchanges);
|
|
139
139
|
const allByRoute = groupByRoute(input.exchanges);
|
|
140
|
-
const middlewareNames = (input.structure?.middleware ?? []).map((m) => m.toLowerCase());
|
|
140
|
+
const middlewareNames = (input.structure?.middleware ?? []).map((m) => m.name.toLowerCase());
|
|
141
141
|
const hasGlobalAuth = middlewareNames.some((n) => /auth|jwt|session|guard/.test(n));
|
|
142
142
|
for (const [routeKey, exchange] of lastByRoute) {
|
|
143
143
|
if (looksPublic(exchange.request.path))
|