tlc-claude-code 1.3.0 → 1.4.1

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 (105) hide show
  1. package/dashboard/dist/components/AuditPane.d.ts +30 -0
  2. package/dashboard/dist/components/AuditPane.js +127 -0
  3. package/dashboard/dist/components/AuditPane.test.d.ts +1 -0
  4. package/dashboard/dist/components/AuditPane.test.js +339 -0
  5. package/dashboard/dist/components/CompliancePane.d.ts +39 -0
  6. package/dashboard/dist/components/CompliancePane.js +96 -0
  7. package/dashboard/dist/components/CompliancePane.test.d.ts +1 -0
  8. package/dashboard/dist/components/CompliancePane.test.js +183 -0
  9. package/dashboard/dist/components/SSOPane.d.ts +36 -0
  10. package/dashboard/dist/components/SSOPane.js +71 -0
  11. package/dashboard/dist/components/SSOPane.test.d.ts +1 -0
  12. package/dashboard/dist/components/SSOPane.test.js +155 -0
  13. package/dashboard/dist/components/WorkspaceDocsPane.js +0 -16
  14. package/dashboard/dist/components/WorkspacePane.d.ts +1 -1
  15. package/dashboard/dist/components/ZeroRetentionPane.d.ts +44 -0
  16. package/dashboard/dist/components/ZeroRetentionPane.js +83 -0
  17. package/dashboard/dist/components/ZeroRetentionPane.test.d.ts +1 -0
  18. package/dashboard/dist/components/ZeroRetentionPane.test.js +160 -0
  19. package/package.json +1 -1
  20. package/server/lib/access-control-doc.js +541 -0
  21. package/server/lib/access-control-doc.test.js +672 -0
  22. package/server/lib/adr-generator.js +423 -0
  23. package/server/lib/adr-generator.test.js +586 -0
  24. package/server/lib/agent-progress-monitor.js +223 -0
  25. package/server/lib/agent-progress-monitor.test.js +202 -0
  26. package/server/lib/audit-attribution.js +191 -0
  27. package/server/lib/audit-attribution.test.js +359 -0
  28. package/server/lib/audit-classifier.js +202 -0
  29. package/server/lib/audit-classifier.test.js +209 -0
  30. package/server/lib/audit-command.js +275 -0
  31. package/server/lib/audit-command.test.js +325 -0
  32. package/server/lib/audit-exporter.js +380 -0
  33. package/server/lib/audit-exporter.test.js +464 -0
  34. package/server/lib/audit-logger.js +236 -0
  35. package/server/lib/audit-logger.test.js +364 -0
  36. package/server/lib/audit-query.js +257 -0
  37. package/server/lib/audit-query.test.js +352 -0
  38. package/server/lib/audit-storage.js +269 -0
  39. package/server/lib/audit-storage.test.js +272 -0
  40. package/server/lib/bulk-repo-init.js +342 -0
  41. package/server/lib/bulk-repo-init.test.js +388 -0
  42. package/server/lib/compliance-checklist.js +866 -0
  43. package/server/lib/compliance-checklist.test.js +476 -0
  44. package/server/lib/compliance-command.js +616 -0
  45. package/server/lib/compliance-command.test.js +551 -0
  46. package/server/lib/compliance-reporter.js +692 -0
  47. package/server/lib/compliance-reporter.test.js +707 -0
  48. package/server/lib/data-flow-doc.js +665 -0
  49. package/server/lib/data-flow-doc.test.js +659 -0
  50. package/server/lib/ephemeral-storage.js +249 -0
  51. package/server/lib/ephemeral-storage.test.js +254 -0
  52. package/server/lib/evidence-collector.js +627 -0
  53. package/server/lib/evidence-collector.test.js +901 -0
  54. package/server/lib/flow-diagram-generator.js +474 -0
  55. package/server/lib/flow-diagram-generator.test.js +446 -0
  56. package/server/lib/idp-manager.js +626 -0
  57. package/server/lib/idp-manager.test.js +587 -0
  58. package/server/lib/memory-exclusion.js +326 -0
  59. package/server/lib/memory-exclusion.test.js +241 -0
  60. package/server/lib/mfa-handler.js +452 -0
  61. package/server/lib/mfa-handler.test.js +490 -0
  62. package/server/lib/oauth-flow.js +375 -0
  63. package/server/lib/oauth-flow.test.js +487 -0
  64. package/server/lib/oauth-registry.js +190 -0
  65. package/server/lib/oauth-registry.test.js +306 -0
  66. package/server/lib/readme-generator.js +490 -0
  67. package/server/lib/readme-generator.test.js +493 -0
  68. package/server/lib/repo-dependency-tracker.js +261 -0
  69. package/server/lib/repo-dependency-tracker.test.js +350 -0
  70. package/server/lib/retention-policy.js +281 -0
  71. package/server/lib/retention-policy.test.js +486 -0
  72. package/server/lib/role-mapper.js +236 -0
  73. package/server/lib/role-mapper.test.js +395 -0
  74. package/server/lib/saml-provider.js +765 -0
  75. package/server/lib/saml-provider.test.js +643 -0
  76. package/server/lib/security-policy-generator.js +682 -0
  77. package/server/lib/security-policy-generator.test.js +544 -0
  78. package/server/lib/sensitive-detector.js +112 -0
  79. package/server/lib/sensitive-detector.test.js +209 -0
  80. package/server/lib/service-interaction-diagram.js +700 -0
  81. package/server/lib/service-interaction-diagram.test.js +638 -0
  82. package/server/lib/service-summary.js +553 -0
  83. package/server/lib/service-summary.test.js +619 -0
  84. package/server/lib/session-purge.js +460 -0
  85. package/server/lib/session-purge.test.js +312 -0
  86. package/server/lib/sso-command.js +544 -0
  87. package/server/lib/sso-command.test.js +552 -0
  88. package/server/lib/sso-session.js +492 -0
  89. package/server/lib/sso-session.test.js +670 -0
  90. package/server/lib/workspace-command.js +249 -0
  91. package/server/lib/workspace-command.test.js +264 -0
  92. package/server/lib/workspace-config.js +270 -0
  93. package/server/lib/workspace-config.test.js +312 -0
  94. package/server/lib/workspace-docs-command.js +547 -0
  95. package/server/lib/workspace-docs-command.test.js +692 -0
  96. package/server/lib/workspace-memory.js +451 -0
  97. package/server/lib/workspace-memory.test.js +403 -0
  98. package/server/lib/workspace-scanner.js +452 -0
  99. package/server/lib/workspace-scanner.test.js +677 -0
  100. package/server/lib/workspace-test-runner.js +315 -0
  101. package/server/lib/workspace-test-runner.test.js +294 -0
  102. package/server/lib/zero-retention-command.js +439 -0
  103. package/server/lib/zero-retention-command.test.js +448 -0
  104. package/server/lib/zero-retention.js +322 -0
  105. package/server/lib/zero-retention.test.js +258 -0
@@ -0,0 +1,306 @@
1
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
+ import {
3
+ createOAuthRegistry,
4
+ PROVIDER_DEFAULTS,
5
+ validateProviderConfig,
6
+ } from './oauth-registry.js';
7
+
8
+ describe('oauth-registry', () => {
9
+ let registry;
10
+
11
+ beforeEach(() => {
12
+ registry = createOAuthRegistry();
13
+ });
14
+
15
+ describe('PROVIDER_DEFAULTS', () => {
16
+ it('supports GitHub provider defaults', () => {
17
+ expect(PROVIDER_DEFAULTS.github).toBeDefined();
18
+ expect(PROVIDER_DEFAULTS.github.authUrl).toBe('https://github.com/login/oauth/authorize');
19
+ expect(PROVIDER_DEFAULTS.github.tokenUrl).toBe('https://github.com/login/oauth/access_token');
20
+ expect(PROVIDER_DEFAULTS.github.userInfoUrl).toBe('https://api.github.com/user');
21
+ expect(PROVIDER_DEFAULTS.github.scopes).toContain('read:user');
22
+ expect(PROVIDER_DEFAULTS.github.scopes).toContain('user:email');
23
+ });
24
+
25
+ it('supports Google provider defaults', () => {
26
+ expect(PROVIDER_DEFAULTS.google).toBeDefined();
27
+ expect(PROVIDER_DEFAULTS.google.authUrl).toBe('https://accounts.google.com/o/oauth2/v2/auth');
28
+ expect(PROVIDER_DEFAULTS.google.tokenUrl).toBe('https://oauth2.googleapis.com/token');
29
+ expect(PROVIDER_DEFAULTS.google.userInfoUrl).toBe('https://www.googleapis.com/oauth2/v2/userinfo');
30
+ expect(PROVIDER_DEFAULTS.google.scopes).toContain('openid');
31
+ expect(PROVIDER_DEFAULTS.google.scopes).toContain('email');
32
+ expect(PROVIDER_DEFAULTS.google.scopes).toContain('profile');
33
+ });
34
+
35
+ it('supports Azure AD provider defaults', () => {
36
+ expect(PROVIDER_DEFAULTS.azuread).toBeDefined();
37
+ expect(PROVIDER_DEFAULTS.azuread.authUrl).toBe('https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize');
38
+ expect(PROVIDER_DEFAULTS.azuread.tokenUrl).toBe('https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token');
39
+ expect(PROVIDER_DEFAULTS.azuread.userInfoUrl).toBe('https://graph.microsoft.com/v1.0/me');
40
+ expect(PROVIDER_DEFAULTS.azuread.scopes).toContain('openid');
41
+ expect(PROVIDER_DEFAULTS.azuread.scopes).toContain('email');
42
+ expect(PROVIDER_DEFAULTS.azuread.scopes).toContain('profile');
43
+ });
44
+ });
45
+
46
+ describe('registerProvider', () => {
47
+ it('adds provider to registry', () => {
48
+ const config = {
49
+ clientId: 'test-client-id',
50
+ clientSecret: 'test-client-secret',
51
+ authUrl: 'https://auth.example.com/authorize',
52
+ tokenUrl: 'https://auth.example.com/token',
53
+ };
54
+
55
+ registry.registerProvider('custom', config);
56
+
57
+ const provider = registry.getProvider('custom');
58
+ expect(provider).not.toBeNull();
59
+ expect(provider.clientId).toBe('test-client-id');
60
+ expect(provider.clientSecret).toBe('test-client-secret');
61
+ });
62
+
63
+ it('validates required fields (clientId, clientSecret, authUrl, tokenUrl)', () => {
64
+ // Missing clientId
65
+ expect(() => registry.registerProvider('test', {
66
+ clientSecret: 'secret',
67
+ authUrl: 'https://auth.example.com/authorize',
68
+ tokenUrl: 'https://auth.example.com/token',
69
+ })).toThrow(/clientId/i);
70
+
71
+ // Missing clientSecret
72
+ expect(() => registry.registerProvider('test', {
73
+ clientId: 'id',
74
+ authUrl: 'https://auth.example.com/authorize',
75
+ tokenUrl: 'https://auth.example.com/token',
76
+ })).toThrow(/clientSecret/i);
77
+
78
+ // Missing authUrl
79
+ expect(() => registry.registerProvider('test', {
80
+ clientId: 'id',
81
+ clientSecret: 'secret',
82
+ tokenUrl: 'https://auth.example.com/token',
83
+ })).toThrow(/authUrl/i);
84
+
85
+ // Missing tokenUrl
86
+ expect(() => registry.registerProvider('test', {
87
+ clientId: 'id',
88
+ clientSecret: 'secret',
89
+ authUrl: 'https://auth.example.com/authorize',
90
+ })).toThrow(/tokenUrl/i);
91
+ });
92
+
93
+ it('merges with provider defaults when using known provider name', () => {
94
+ registry.registerProvider('github', {
95
+ clientId: 'my-github-client',
96
+ clientSecret: 'my-github-secret',
97
+ });
98
+
99
+ const provider = registry.getProvider('github');
100
+ expect(provider.clientId).toBe('my-github-client');
101
+ expect(provider.authUrl).toBe('https://github.com/login/oauth/authorize');
102
+ expect(provider.tokenUrl).toBe('https://github.com/login/oauth/access_token');
103
+ expect(provider.scopes).toContain('read:user');
104
+ });
105
+
106
+ it('allows overriding defaults', () => {
107
+ registry.registerProvider('github', {
108
+ clientId: 'my-github-client',
109
+ clientSecret: 'my-github-secret',
110
+ scopes: ['repo', 'user'],
111
+ });
112
+
113
+ const provider = registry.getProvider('github');
114
+ expect(provider.scopes).toContain('repo');
115
+ expect(provider.scopes).toContain('user');
116
+ expect(provider.scopes).not.toContain('read:user');
117
+ });
118
+ });
119
+
120
+ describe('getProvider', () => {
121
+ it('returns registered provider', () => {
122
+ registry.registerProvider('github', {
123
+ clientId: 'client-id',
124
+ clientSecret: 'client-secret',
125
+ });
126
+
127
+ const provider = registry.getProvider('github');
128
+ expect(provider).not.toBeNull();
129
+ expect(provider.clientId).toBe('client-id');
130
+ });
131
+
132
+ it('returns null for unknown provider', () => {
133
+ const provider = registry.getProvider('unknown');
134
+ expect(provider).toBeNull();
135
+ });
136
+
137
+ it('is case-insensitive for provider names', () => {
138
+ registry.registerProvider('GitHub', {
139
+ clientId: 'client-id',
140
+ clientSecret: 'client-secret',
141
+ });
142
+
143
+ expect(registry.getProvider('github')).not.toBeNull();
144
+ expect(registry.getProvider('GITHUB')).not.toBeNull();
145
+ expect(registry.getProvider('GitHub')).not.toBeNull();
146
+ });
147
+ });
148
+
149
+ describe('listProviders', () => {
150
+ it('returns all registered providers', () => {
151
+ registry.registerProvider('github', {
152
+ clientId: 'github-client',
153
+ clientSecret: 'github-secret',
154
+ });
155
+ registry.registerProvider('google', {
156
+ clientId: 'google-client',
157
+ clientSecret: 'google-secret',
158
+ });
159
+
160
+ const providers = registry.listProviders();
161
+ expect(providers).toHaveLength(2);
162
+ expect(providers.map(p => p.name)).toContain('github');
163
+ expect(providers.map(p => p.name)).toContain('google');
164
+ });
165
+
166
+ it('returns empty array when no providers registered', () => {
167
+ const providers = registry.listProviders();
168
+ expect(providers).toEqual([]);
169
+ });
170
+
171
+ it('does not expose client secrets in list', () => {
172
+ registry.registerProvider('github', {
173
+ clientId: 'github-client',
174
+ clientSecret: 'github-secret',
175
+ });
176
+
177
+ const providers = registry.listProviders();
178
+ expect(providers[0].clientSecret).toBeUndefined();
179
+ expect(providers[0].clientId).toBe('github-client');
180
+ });
181
+ });
182
+
183
+ describe('loadFromConfig', () => {
184
+ it('reads providers from .tlc.json config', () => {
185
+ const config = {
186
+ oauth: {
187
+ providers: {
188
+ github: {
189
+ clientId: 'config-github-client',
190
+ clientSecret: 'config-github-secret',
191
+ },
192
+ google: {
193
+ clientId: 'config-google-client',
194
+ clientSecret: 'config-google-secret',
195
+ },
196
+ },
197
+ },
198
+ };
199
+
200
+ registry.loadFromConfig(config);
201
+
202
+ expect(registry.getProvider('github')).not.toBeNull();
203
+ expect(registry.getProvider('github').clientId).toBe('config-github-client');
204
+ expect(registry.getProvider('google')).not.toBeNull();
205
+ expect(registry.getProvider('google').clientId).toBe('config-google-client');
206
+ });
207
+
208
+ it('handles missing oauth section', () => {
209
+ const config = {};
210
+
211
+ expect(() => registry.loadFromConfig(config)).not.toThrow();
212
+ expect(registry.listProviders()).toEqual([]);
213
+ });
214
+
215
+ it('handles missing providers section', () => {
216
+ const config = { oauth: {} };
217
+
218
+ expect(() => registry.loadFromConfig(config)).not.toThrow();
219
+ expect(registry.listProviders()).toEqual([]);
220
+ });
221
+
222
+ it('validates each provider config', () => {
223
+ const config = {
224
+ oauth: {
225
+ providers: {
226
+ github: {
227
+ clientId: 'github-client',
228
+ // Missing clientSecret - should fail
229
+ },
230
+ },
231
+ },
232
+ };
233
+
234
+ expect(() => registry.loadFromConfig(config)).toThrow(/clientSecret/i);
235
+ });
236
+ });
237
+
238
+ describe('validateConfig', () => {
239
+ it('returns errors for invalid config', () => {
240
+ const errors = validateProviderConfig({});
241
+ expect(errors).toContain('clientId is required');
242
+ expect(errors).toContain('clientSecret is required');
243
+ });
244
+
245
+ it('returns errors for missing auth URLs when no defaults', () => {
246
+ const errors = validateProviderConfig({
247
+ clientId: 'id',
248
+ clientSecret: 'secret',
249
+ });
250
+ expect(errors).toContain('authUrl is required');
251
+ expect(errors).toContain('tokenUrl is required');
252
+ });
253
+
254
+ it('returns empty array for valid config', () => {
255
+ const errors = validateProviderConfig({
256
+ clientId: 'id',
257
+ clientSecret: 'secret',
258
+ authUrl: 'https://auth.example.com/authorize',
259
+ tokenUrl: 'https://auth.example.com/token',
260
+ });
261
+ expect(errors).toEqual([]);
262
+ });
263
+
264
+ it('accepts config with known provider name (uses defaults)', () => {
265
+ const errors = validateProviderConfig({
266
+ clientId: 'id',
267
+ clientSecret: 'secret',
268
+ }, 'github');
269
+ expect(errors).toEqual([]);
270
+ });
271
+ });
272
+
273
+ describe('removeProvider', () => {
274
+ it('removes a registered provider', () => {
275
+ registry.registerProvider('github', {
276
+ clientId: 'client-id',
277
+ clientSecret: 'client-secret',
278
+ });
279
+
280
+ expect(registry.getProvider('github')).not.toBeNull();
281
+
282
+ registry.removeProvider('github');
283
+
284
+ expect(registry.getProvider('github')).toBeNull();
285
+ });
286
+
287
+ it('does nothing for unknown provider', () => {
288
+ expect(() => registry.removeProvider('unknown')).not.toThrow();
289
+ });
290
+ });
291
+
292
+ describe('hasProvider', () => {
293
+ it('returns true for registered provider', () => {
294
+ registry.registerProvider('github', {
295
+ clientId: 'client-id',
296
+ clientSecret: 'client-secret',
297
+ });
298
+
299
+ expect(registry.hasProvider('github')).toBe(true);
300
+ });
301
+
302
+ it('returns false for unknown provider', () => {
303
+ expect(registry.hasProvider('unknown')).toBe(false);
304
+ });
305
+ });
306
+ });