@trustnext/ztam-analyzer 1.0.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.
@@ -0,0 +1,542 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * report-generator.js (v2)
5
+ *
6
+ * Gap analysis, strategy selection, complexity scoring, and all output formats.
7
+ * Language: bridges, never rewrites. ZTAM *provides* req.user — the report
8
+ * recommends how to connect that to whatever pattern the client already uses.
9
+ *
10
+ * READ-ONLY. Pure function — no side effects.
11
+ */
12
+
13
+ // ── Conflict / Gap Rules ──────────────────────────────────────────────────────
14
+ // Each rule: { id, check(result), conflict{title, detail}, bridgeHint }
15
+
16
+ const GAP_RULES = [
17
+ {
18
+ id: 'session_bridge',
19
+ check({ auth }) {
20
+ return auth.userObjectPattern === 'req.session.user';
21
+ },
22
+ conflict: {
23
+ title: 'Session bridge needed',
24
+ detail: 'App reads from req.session.user; ZTAM provides req.user after cookie verification.',
25
+ },
26
+ bridgeHint: 'Populate req.session.user from req.user in a bridge middleware (1 file).',
27
+ },
28
+ {
29
+ id: 'custom_context_bridge',
30
+ check({ auth }) {
31
+ return ['req.auth', 'req.currentUser'].includes(auth.userObjectPattern);
32
+ },
33
+ conflict: {
34
+ title: 'Custom context bridge needed',
35
+ detail: `App reads from ${'{auth.userObjectPattern}'}; ZTAM provides req.user after cookie verification.`,
36
+ },
37
+ bridgeHint: 'Map req.user to the custom context key in a bridge middleware (1 file).',
38
+ },
39
+ {
40
+ id: 'role_mapping',
41
+ check({ roles }) {
42
+ return roles.patterns.includes('Role string comparison');
43
+ },
44
+ conflict: {
45
+ title: 'Role mapping needed',
46
+ detail: 'App checks user.role (string scalar); ZTAM provides user.roles[] (array). Review how role information should be mapped.',
47
+ },
48
+ bridgeHint: 'Add: req.user.role = req.user.roles?.[0] inside the bridge middleware.',
49
+ },
50
+ {
51
+ id: 'local_login',
52
+ check({ auth }) { return auth.hasLocalLogin; },
53
+ conflict: {
54
+ title: 'Local Authentication Review Required',
55
+ detail: 'The ZTAM Gateway handles login. The local /login handler should be reviewed and likely redirected to /ztam/login.',
56
+ },
57
+ bridgeHint: 'Review local /login handler — redirect to /ztam/login if appropriate.',
58
+ },
59
+ {
60
+ id: 'local_logout',
61
+ check({ auth }) { return auth.hasLocalLogout; },
62
+ conflict: {
63
+ title: 'Local logout route detected',
64
+ detail: 'The ZTAM Gateway terminates sessions. The local /logout handler should redirect to /ztam/logout.',
65
+ },
66
+ bridgeHint: 'Update /logout to res.redirect(\'/ztam/logout\').',
67
+ },
68
+ {
69
+ id: 'jwt_verify_redundant',
70
+ check({ auth, packageJson }) {
71
+ if (packageJson && packageJson.name === '@trustnext/ztam-middleware') return false;
72
+ return auth.libraries.includes('JWT (jsonwebtoken)');
73
+ },
74
+ conflict: {
75
+ title: 'JWT verification detected',
76
+ detail: 'Review whether this overlaps with ZTAM authentication responsibilities.',
77
+ },
78
+ bridgeHint: 'Review manual jwt.verify() calls from application code.',
79
+ },
80
+ {
81
+ id: 'passport_local_conflict',
82
+ check({ auth }) { return auth.libraries.includes('Passport'); },
83
+ conflict: {
84
+ title: 'Passport local authentication detected',
85
+ detail: 'Review whether this overlaps with ZTAM authentication responsibilities.',
86
+ },
87
+ bridgeHint: 'Review whether Passport local strategy is still required once ZTAM handles identity.',
88
+ },
89
+ {
90
+ id: 'keycloak_adapter_conflict',
91
+ check({ auth }) { return auth.libraries.includes('Keycloak'); },
92
+ conflict: {
93
+ title: 'Existing Keycloak adapter conflicts',
94
+ detail: 'ZTAM manages Keycloak centrally. A local keycloak-connect adapter will conflict.',
95
+ },
96
+ bridgeHint: 'Remove keycloak-connect from the application — the ZTAM Gateway owns the Keycloak integration.',
97
+ },
98
+ ];
99
+
100
+ // ── Strategy Selection ────────────────────────────────────────────────────────
101
+
102
+ function selectStrategy(detectionResult, conflicts) {
103
+ const { auth, session } = detectionResult;
104
+ const conflictIds = new Set(conflicts.map(c => c.id));
105
+
106
+ if (auth.userObjectPattern === 'req.user' && !conflictIds.has('role_mapping')) {
107
+ return {
108
+ id: 'direct_integration',
109
+ title: 'Direct Integration',
110
+ reason: 'Application already uses req.user — ZTAM middleware populates it directly.',
111
+ considerations: [
112
+ 'Directly mount @trustnext/ztam-middleware before protected routes.',
113
+ 'No custom mapping layer is required.'
114
+ ]
115
+ };
116
+ }
117
+
118
+ if (auth.userObjectPattern === 'req.session.user' && session.approach === 'express-session') {
119
+ return {
120
+ id: 'session_bridge',
121
+ title: 'Session Bridge',
122
+ reason: `Application uses express-session with ${auth.userObjectPattern}. ZTAM provides req.user — a bridge populates the session without changing existing auth middleware.`,
123
+ considerations: [
124
+ 'Review how authenticated user information should be exposed through the application\'s existing session model.',
125
+ conflictIds.has('role_mapping') ? 'Review how role information should be represented within the application\'s authorization model.' : null
126
+ ].filter(Boolean)
127
+ };
128
+ }
129
+
130
+ if (['req.auth', 'req.currentUser'].includes(auth.userObjectPattern)) {
131
+ const key = auth.userObjectPattern;
132
+ return {
133
+ id: 'custom_context_bridge',
134
+ title: 'Custom Context Bridge',
135
+ reason: `Application uses ${key}. ZTAM provides req.user — a bridge maps it to the expected key.`,
136
+ considerations: [
137
+ 'Review how authenticated user information should be mapped to the expected custom context property.'
138
+ ]
139
+ };
140
+ }
141
+
142
+ return {
143
+ id: 'greenfield_integration',
144
+ title: 'Greenfield Integration',
145
+ reason: 'No existing authentication pattern detected. Add ZTAM middleware directly.',
146
+ considerations: [
147
+ 'Mount @trustnext/ztam-middleware to establish the req.user context.',
148
+ 'Protect sensitive routes using the provided protect() guards.'
149
+ ]
150
+ };
151
+ }
152
+
153
+ // ── Main ──────────────────────────────────────────────────────────────────────
154
+
155
+ function generateReport(detectionResult) {
156
+ const { framework, allFrameworks, auth, session, roles, allAffectedFiles, referenceCounts, projectPath } = detectionResult;
157
+
158
+ // Resolve dynamic conflict detail (template strings with runtime values)
159
+ const conflicts = GAP_RULES
160
+ .filter(rule => rule.check(detectionResult))
161
+ .map(rule => ({
162
+ id: rule.id,
163
+ title: rule.conflict.title,
164
+ detail: rule.conflict.detail.replace('{auth.userObjectPattern}', auth.userObjectPattern || ''),
165
+ bridgeHint: rule.bridgeHint,
166
+ }));
167
+
168
+ const strategy = selectStrategy(detectionResult, conflicts);
169
+
170
+ // Action Plan items — derived from detected conflicts
171
+ const requiredChanges = [];
172
+ requiredChanges.push({ title: 'Install @trustnext/ztam-middleware', description: null });
173
+
174
+ const conflictIds = new Set(conflicts.map(c => c.id));
175
+
176
+ if (conflictIds.has('session_bridge')) {
177
+ requiredChanges.push({
178
+ title: 'Session Mapping',
179
+ description: `The application uses ${auth.userObjectPattern}.\nZTAM provides authenticated users through req.user.\nReview how authenticated user context should be mapped.`
180
+ });
181
+ }
182
+
183
+ if (conflictIds.has('custom_context_bridge')) {
184
+ requiredChanges.push({
185
+ title: 'User Context Mapping',
186
+ description: `The application uses ${auth.userObjectPattern}.\nZTAM provides authenticated users through req.user.\nReview how the authenticated user context should be exposed to the application.`
187
+ });
188
+ }
189
+
190
+ if (conflictIds.has('role_mapping')) {
191
+ requiredChanges.push({
192
+ title: 'Role Representation',
193
+ description: 'The application checks roles as a string scalar (user.role).\nZTAM provides roles as an array (user.roles[]).\nReview how role information should be represented within the application.'
194
+ });
195
+ }
196
+
197
+ if (conflictIds.has('local_login') || conflictIds.has('local_logout')) {
198
+ const loginDetail = conflictIds.has('local_login') ? '- Local login route detected — review for compatibility with gateway authentication.' : null;
199
+ const logoutDetail = conflictIds.has('local_logout') ? '- Local logout route detected — review for compatibility with gateway session termination.' : null;
200
+ requiredChanges.push({
201
+ title: 'Authentication Routes',
202
+ description: [loginDetail, logoutDetail].filter(Boolean).join('\n')
203
+ });
204
+ }
205
+
206
+ if (conflictIds.has('jwt_verify_redundant')) {
207
+ requiredChanges.push({
208
+ title: 'JWT Verification',
209
+ description: 'JWT verification logic detected in the application.\nZTAM middleware handles token verification at the gateway level.\nReview whether in-application jwt.verify() calls remain necessary.'
210
+ });
211
+ }
212
+
213
+ if (conflictIds.has('passport_local_conflict')) {
214
+ requiredChanges.push({
215
+ title: 'Passport Strategy Review',
216
+ description: 'Passport authentication is detected.\nZTAM handles identity through the gateway.\nReview whether the Passport local strategy remains necessary after integration.'
217
+ });
218
+ }
219
+
220
+ if (conflictIds.has('keycloak_adapter_conflict')) {
221
+ requiredChanges.push({
222
+ title: 'Keycloak Adapter Review',
223
+ description: 'A local Keycloak adapter is detected.\nZTAM manages Keycloak centrally at the gateway level.\nReview whether the local adapter would conflict with the ZTAM integration.'
224
+ });
225
+ }
226
+
227
+ if (roles.customGuards.length > 0) {
228
+ const middlewareList = roles.customGuards.map(g => `- ${g}`).join('\n');
229
+ requiredChanges.push({
230
+ title: 'Protected Route Middleware',
231
+ description: `The following middleware guards were detected:\n${middlewareList}\nReview whether these guards remain compatible after ZTAM is introduced.`
232
+ });
233
+ } else if (auth.libraries.length > 0 && !conflictIds.has('session_bridge') && !conflictIds.has('custom_context_bridge')) {
234
+ requiredChanges.push({
235
+ title: 'Authentication Middleware',
236
+ description: 'Review existing authentication middleware to confirm compatibility with ZTAM.'
237
+ });
238
+ }
239
+
240
+ if (auth.allUserPatterns && auth.allUserPatterns.length > 1) {
241
+ const secondaryPatterns = auth.allUserPatterns.filter(p => p !== 'req.user' && p !== auth.userObjectPattern);
242
+ if (secondaryPatterns.length > 0) {
243
+ requiredChanges.push({
244
+ title: 'Additional Context',
245
+ description: `The application also references ${secondaryPatterns.join(', ')}.\nReview whether authenticated user information should continue to be exposed through this property after integration.`
246
+ });
247
+ }
248
+ }
249
+
250
+ const suggestedExamples = [];
251
+ if (strategy.id === 'session_bridge') {
252
+ suggestedExamples.push({
253
+ title: 'Session Bridge',
254
+ currentPattern: auth.userObjectPattern,
255
+ ztamPattern: 'req.user',
256
+ description: 'Consider introducing a middleware layer that maps authenticated user information into the application\'s existing session structure.\n\nThis is only a suggested approach and is not automatically applied.'
257
+ });
258
+ } else if (strategy.id === 'custom_context_bridge') {
259
+ suggestedExamples.push({
260
+ title: 'Custom Context Bridge',
261
+ currentPattern: auth.userObjectPattern,
262
+ ztamPattern: 'req.user',
263
+ description: 'Consider introducing a middleware layer that maps authenticated user information into the custom context property.\n\nThis is only a suggested approach and is not automatically applied.'
264
+ });
265
+ }
266
+
267
+ const terminal = _renderTerminal({ projectPath, framework, allFrameworks, auth, session, roles, allAffectedFiles, referenceCounts, conflicts, strategy, requiredChanges, suggestedExamples });
268
+ const markdown = _renderMarkdown({ projectPath, framework, allFrameworks, auth, session, roles, allAffectedFiles, referenceCounts, conflicts, strategy, requiredChanges, suggestedExamples });
269
+ const json = _renderJson({ projectPath, framework, auth, session, roles, conflicts, strategy, allAffectedFiles, referenceCounts, requiredChanges, suggestedExamples });
270
+
271
+ return { terminal, markdown, json, conflicts, strategy, requiredChanges, suggestedExamples };
272
+ }
273
+
274
+ // ── Terminal Renderer ─────────────────────────────────────────────────────────
275
+
276
+ function _renderTerminal(r) {
277
+ const LINE = '═'.repeat(62);
278
+ const THIN = '─'.repeat(62);
279
+ const ICON = { low: '🟢', medium: '🟡', high: '🔴' };
280
+ const lines = [];
281
+
282
+ lines.push('');
283
+ lines.push(LINE);
284
+ lines.push(' ZTAM Integration Analyzer — Report');
285
+ lines.push(LINE);
286
+ lines.push('');
287
+ lines.push(`Project: ${r.projectPath}`);
288
+ lines.push('');
289
+
290
+ const fwStr = r.allFrameworks.length > 0
291
+ ? r.allFrameworks.map(f => `${f.name} [${f.confidence}]`).join(', ')
292
+ : 'Unknown';
293
+ lines.push(`Framework: ${fwStr}`);
294
+ lines.push(`Authentication: ${r.auth.libraries.join(', ') || 'None detected'}`);
295
+ lines.push(`Session Storage: ${r.session.approach} — Store: ${r.session.store}`);
296
+
297
+ const uop = r.auth.allUserPatterns.length > 0 ? r.auth.allUserPatterns.join(', ') : 'Not detected';
298
+ lines.push(`User Object: ${uop}`);
299
+
300
+ const roleStr = [
301
+ ...r.roles.libraries,
302
+ ...(r.roles.customGuards.length > 0 ? [`Custom: ${r.roles.customGuards.join(', ')}`] : []),
303
+ ...r.roles.patterns,
304
+ ].join(', ') || 'None detected';
305
+ lines.push(`Authorization: ${roleStr}`);
306
+ lines.push('');
307
+
308
+ if (r.allAffectedFiles.length > 0) {
309
+ lines.push(THIN);
310
+ lines.push('Potential Touch Points:');
311
+ r.allAffectedFiles.forEach(f => lines.push(` - ${f}`));
312
+ lines.push('');
313
+ }
314
+
315
+ const refKeys = Object.keys(r.referenceCounts);
316
+ if (refKeys.length > 0) {
317
+ lines.push(THIN);
318
+ lines.push('Detected References:');
319
+ refKeys.forEach(k => lines.push(` - ${k}: ${r.referenceCounts[k]} occurrences`));
320
+ lines.push('');
321
+ }
322
+
323
+ lines.push(THIN);
324
+ if (r.conflicts.length === 0) {
325
+ lines.push('Integration Findings: ✓ None — clean integration possible');
326
+ } else {
327
+ lines.push(`Integration Findings: ${r.conflicts.length}`);
328
+ lines.push('');
329
+ r.conflicts.forEach((c, i) => {
330
+ lines.push(` [${i + 1}] ${c.title}`);
331
+ lines.push(` ${c.detail}`);
332
+ });
333
+ }
334
+ lines.push('');
335
+
336
+ lines.push(THIN);
337
+ lines.push(`Recommended Integration Strategy: ${r.strategy.title}`);
338
+ lines.push('');
339
+ lines.push(` Reason: ${r.strategy.reason}`);
340
+ if (r.strategy.considerations && r.strategy.considerations.length > 0) {
341
+ lines.push('');
342
+ lines.push(' Integration Considerations:');
343
+ r.strategy.considerations.forEach(c => lines.push(` - ${c}`));
344
+ }
345
+ lines.push('');
346
+
347
+ // ── Integration Guidance ──────────────────────────────────────────────────
348
+ // Only show a gap when the PRIMARY user context differs from what ZTAM provides.
349
+ const primaryPattern = r.auth.userObjectPattern;
350
+ const hasContextGap = primaryPattern && primaryPattern !== 'req.user';
351
+
352
+ if (hasContextGap) {
353
+ lines.push(THIN);
354
+ lines.push('Integration Guidance');
355
+ lines.push('');
356
+ lines.push(` Application expects: ${primaryPattern}`);
357
+ lines.push(` ZTAM provides: req.user`);
358
+ lines.push('');
359
+ lines.push(' Gap: The application and ZTAM use different user context properties.');
360
+ lines.push(' An integration layer between ZTAM middleware and application routes');
361
+ lines.push(' is the area to review.');
362
+ lines.push('');
363
+ }
364
+
365
+ // ── Action Plan ──────────────────────────────────────────────────────
366
+ lines.push(THIN);
367
+ lines.push('Action Plan');
368
+ lines.push('');
369
+ r.requiredChanges.forEach((rc, i) => {
370
+ lines.push(` ${i + 1}. ${rc.title}`);
371
+ if (rc.description) {
372
+ rc.description.split('\n').forEach(l => lines.push(` ${l}`));
373
+ }
374
+ lines.push('');
375
+ });
376
+
377
+ // ── Suggested Architecture Pattern ─────────────────────────────────────────────────
378
+ if (r.suggestedExamples.length > 0) {
379
+ lines.push(THIN);
380
+ lines.push('Suggested Architecture Pattern');
381
+ lines.push('');
382
+ r.suggestedExamples.forEach(se => {
383
+ lines.push(` Strategy: ${se.title}`);
384
+ lines.push('');
385
+ lines.push(` Middleware execution order:`);
386
+ lines.push(' [ ZTAM Middleware ]');
387
+ lines.push(' ↓');
388
+ lines.push(' [ Application Integration Layer ]');
389
+ lines.push(' ↓');
390
+ lines.push(' [ Existing Protected Routes ]');
391
+ lines.push('');
392
+ se.description.split('\n').forEach(l => lines.push(` ${l}`));
393
+ lines.push('');
394
+ });
395
+ }
396
+
397
+ lines.push(LINE);
398
+ lines.push('');
399
+
400
+ return lines.join('\n');
401
+ }
402
+
403
+ // ── Markdown Renderer ─────────────────────────────────────────────────────────
404
+
405
+ function _renderMarkdown(r) {
406
+ const now = new Date().toISOString().replace('T', ' ').substring(0, 19);
407
+ const ICON = { low: '🟢', medium: '🟡', high: '🔴' };
408
+ const lines = [];
409
+
410
+ lines.push('# ZTAM Integration Report');
411
+ lines.push('');
412
+ lines.push(`> **Generated:** ${now}`);
413
+ lines.push(`> **Project:** \`${r.projectPath}\``);
414
+ lines.push('');
415
+
416
+ lines.push('## Detection Summary');
417
+ lines.push('');
418
+ lines.push('| Property | Value |');
419
+ lines.push('|---|---|');
420
+ const fw = r.allFrameworks.map(f => `${f.name} (${f.confidence})`).join(', ') || 'Unknown';
421
+ lines.push(`| Framework | ${fw} |`);
422
+ lines.push(`| Authentication | ${r.auth.libraries.join(', ') || 'None'} |`);
423
+ lines.push(`| Session | ${r.session.approach} — ${r.session.store} |`);
424
+ lines.push(`| User Object | ${r.auth.allUserPatterns.join(', ') || 'Not detected'} |`);
425
+ const roleStr = [...r.roles.libraries, ...r.roles.patterns, ...r.roles.customGuards].join(', ') || 'None';
426
+ lines.push(`| Authorization | ${roleStr} |`);
427
+ lines.push('');
428
+
429
+ if (r.allAffectedFiles.length > 0) {
430
+ lines.push('## Potential Touch Points');
431
+ r.allAffectedFiles.forEach(f => lines.push(`- \`${f}\``));
432
+ lines.push('');
433
+ }
434
+
435
+ const refKeys = Object.keys(r.referenceCounts);
436
+ if (refKeys.length > 0) {
437
+ lines.push('## Detected References');
438
+ refKeys.forEach(k => lines.push(`- \`${k}\`: ${r.referenceCounts[k]} occurrences`));
439
+ lines.push('');
440
+ }
441
+
442
+ lines.push('## Integration Findings');
443
+ if (r.conflicts.length === 0) {
444
+ lines.push('✅ No integration findings — clean integration possible.');
445
+ } else {
446
+ r.conflicts.forEach((c, i) => {
447
+ lines.push(`### ${i + 1}. ${c.title}`);
448
+ lines.push(`> ${c.detail}`);
449
+ lines.push('');
450
+ lines.push(`**Bridge:** ${c.bridgeHint}`);
451
+ lines.push('');
452
+ });
453
+ }
454
+
455
+ lines.push('## Recommended Integration Strategy');
456
+ lines.push('');
457
+ lines.push(`**Strategy:** ${r.strategy.title}`);
458
+ lines.push('');
459
+ lines.push(`**Reason:** ${r.strategy.reason}`);
460
+ if (r.strategy.considerations && r.strategy.considerations.length > 0) {
461
+ lines.push('');
462
+ lines.push('**Integration Considerations:**');
463
+ r.strategy.considerations.forEach(c => lines.push(`- ${c}`));
464
+ }
465
+ lines.push('');
466
+
467
+ lines.push('## Required Changes');
468
+ lines.push('');
469
+ r.requiredChanges.forEach((rc, i) => {
470
+ lines.push(`### ${i + 1}. ${rc.title}`);
471
+ if (rc.description) {
472
+ rc.description.split('\n').forEach(l => lines.push(`${l}`));
473
+ }
474
+ lines.push('');
475
+ });
476
+
477
+ if (r.suggestedExamples.length > 0) {
478
+ lines.push('## Suggested Example');
479
+ lines.push('');
480
+ r.suggestedExamples.forEach(se => {
481
+ lines.push(`### ${se.title}`);
482
+ lines.push('');
483
+ lines.push(`**Current pattern:** \`${se.currentPattern}\``);
484
+ lines.push('');
485
+ lines.push(`**ZTAM pattern:** \`${se.ztamPattern}\``);
486
+ lines.push('');
487
+ se.description.split('\n').forEach(l => lines.push(`${l}`));
488
+ lines.push('');
489
+ });
490
+ }
491
+
492
+ return lines.join('\n');
493
+ }
494
+
495
+ // ── JSON Renderer ─────────────────────────────────────────────────────────────
496
+
497
+ function _renderJson(r) {
498
+ const { framework, auth, session, roles, conflicts, strategy, projectPath, allAffectedFiles, referenceCounts, requiredChanges, suggestedExamples } = r;
499
+
500
+ // Determine role type
501
+ let roleType = 'none';
502
+ if (roles.patterns.includes('Role array check')) roleType = 'array';
503
+ else if (roles.patterns.includes('Role string comparison')) roleType = 'string';
504
+ else if (roles.patterns.includes('Permission check')) roleType = 'permission';
505
+
506
+ return JSON.stringify({
507
+ schemaVersion: '2.0',
508
+ generatedAt: new Date().toISOString(),
509
+ projectPath,
510
+ framework: {
511
+ name: framework.name,
512
+ confidence: framework.confidence,
513
+ },
514
+ authentication: {
515
+ libraries: auth.libraries,
516
+ userObjectPattern: auth.userObjectPattern,
517
+ allUserPatterns: auth.allUserPatterns,
518
+ hasLocalLogin: auth.hasLocalLogin,
519
+ hasLocalLogout: auth.hasLocalLogout,
520
+ },
521
+ session: {
522
+ approach: session.approach,
523
+ store: session.store,
524
+ cookieBased: session.cookieBased,
525
+ secureCookie: session.secureCookie,
526
+ },
527
+ authorization: {
528
+ libraries: roles.libraries,
529
+ patterns: roles.patterns,
530
+ customGuards: roles.customGuards,
531
+ roleType,
532
+ },
533
+ conflicts: conflicts.map(c => c.id),
534
+ recommendedStrategy: strategy.id,
535
+ integrationCandidates: allAffectedFiles,
536
+ referenceCounts,
537
+ requiredChanges,
538
+ suggestedExamples
539
+ }, null, 2);
540
+ }
541
+
542
+ module.exports = { generateReport };
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@trustnext/ztam-analyzer",
3
+ "version": "1.0.0",
4
+ "description": "Read-only ZTAM integration analyzer for Node.js applications",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "ztam-analyzer": "./cli.js"
8
+ },
9
+ "scripts": {
10
+ "analyze": "node cli.js analyze"
11
+ },
12
+ "keywords": ["ztam", "security", "analyzer", "integration", "zero-trust"],
13
+ "author": "TrustNext",
14
+ "license": "MIT",
15
+ "dependencies": {}
16
+ }
package/report.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "schemaVersion": "2.0",
3
+ "generatedAt": "2026-06-25T14:36:40.715Z",
4
+ "projectPath": "/home/heisenberg/Desktop/test app 1",
5
+ "framework": {
6
+ "name": "Express",
7
+ "confidence": "high"
8
+ },
9
+ "authentication": {
10
+ "libraries": [
11
+ "express-session"
12
+ ],
13
+ "userObjectPattern": "req.session.user",
14
+ "allUserPatterns": [
15
+ "req.session.user"
16
+ ],
17
+ "hasLocalLogin": false,
18
+ "hasLocalLogout": false
19
+ },
20
+ "session": {
21
+ "approach": "express-session",
22
+ "store": "MySQL",
23
+ "cookieBased": true,
24
+ "secureCookie": null
25
+ },
26
+ "authorization": {
27
+ "libraries": [],
28
+ "patterns": [
29
+ "Role string comparison"
30
+ ],
31
+ "customGuards": [
32
+ "requireRole()",
33
+ "requireAdmin()",
34
+ "requireAuth()"
35
+ ],
36
+ "roleType": "string"
37
+ },
38
+ "conflicts": [
39
+ "session_bridge",
40
+ "role_mapping"
41
+ ],
42
+ "recommendedStrategy": "session_bridge",
43
+ "integrationCandidates": [
44
+ "public/app.js",
45
+ "src/middleware/auth.js",
46
+ "src/routes/adminRoutes.js",
47
+ "src/routes/authRoutes.js",
48
+ "src/routes/managerRoutes.js",
49
+ "src/routes/taskRoutes.js"
50
+ ],
51
+ "referenceCounts": {
52
+ "req.session.user": 32,
53
+ "requireRole": 4,
54
+ "requireAdmin": 12,
55
+ "requireAuth": 8
56
+ },
57
+ "requiredChanges": [
58
+ {
59
+ "title": "Install @trustnext/ztam-middleware",
60
+ "description": null
61
+ },
62
+ {
63
+ "title": "Session Handling",
64
+ "description": "The application uses req.session.user.\nZTAM provides authenticated users through req.user.\nA bridge between these patterns will be needed."
65
+ },
66
+ {
67
+ "title": "Authorization",
68
+ "description": "The application uses custom roles or role mapping.\nZTAM provides roles as an array (roles[]).\nReview how roles should be mapped."
69
+ },
70
+ {
71
+ "title": "Protected Routes",
72
+ "description": "Review routes protected by requireAuth(), requireRole(), requireAdmin(), passport.authenticate(), or similar middleware."
73
+ }
74
+ ],
75
+ "suggestedExamples": [
76
+ {
77
+ "title": "Session Bridge",
78
+ "currentPattern": "req.session.user",
79
+ "ztamPattern": "req.user",
80
+ "description": "Consider introducing a middleware layer that maps authenticated user information into the application's existing session structure.\n\nThis is only a suggested approach and is not automatically applied."
81
+ }
82
+ ],
83
+ "complexity": "medium"
84
+ }