@principal-ai/control-tower-core 0.1.20 → 0.1.22

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.
@@ -1,6 +1,5 @@
1
- import type { TokenPayload, AuthResult, Credentials, CredentialType } from '../types/index.js';
1
+ import type { TokenPayload } from '../types/index.js';
2
2
  export interface IAuthAdapter {
3
- authenticate(credentials: Credentials): Promise<AuthResult>;
4
3
  validateToken(token: string): Promise<TokenPayload>;
5
4
  generateToken?(payload: TokenPayload): Promise<string>;
6
5
  refreshToken?(token: string): Promise<string>;
@@ -8,6 +7,5 @@ export interface IAuthAdapter {
8
7
  getCurrentToken?(): string | null;
9
8
  isAuthRequired?(): boolean;
10
9
  getAuthTimeout?(): number;
11
- getSupportedCredentialTypes?(): CredentialType[];
12
10
  }
13
11
  //# sourceMappingURL=AuthAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AuthAdapter.d.ts","sourceRoot":"","sources":["../../src/abstractions/AuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,YAAY;IAE3B,YAAY,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAG5D,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACpD,aAAa,CAAC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,YAAY,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,WAAW,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG3C,eAAe,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC;IAGlC,cAAc,CAAC,IAAI,OAAO,CAAC;IAC3B,cAAc,CAAC,IAAI,MAAM,CAAC;IAC1B,2BAA2B,CAAC,IAAI,cAAc,EAAE,CAAC;CAClD"}
1
+ {"version":3,"file":"AuthAdapter.d.ts","sourceRoot":"","sources":["../../src/abstractions/AuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,YAAY;IAE3B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAGpD,aAAa,CAAC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,YAAY,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,WAAW,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG3C,eAAe,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC;IAGlC,cAAc,CAAC,IAAI,OAAO,CAAC;IAC3B,cAAc,CAAC,IAAI,MAAM,CAAC;CAC3B"}
@@ -1,12 +1,12 @@
1
1
  import type { IAuthAdapter } from '../../abstractions/AuthAdapter.js';
2
- import type { TokenPayload, AuthResult, Credentials, CredentialType } from '../../types/index.js';
2
+ import type { TokenPayload } from '../../types/index.js';
3
3
  export declare class MockAuthAdapter implements IAuthAdapter {
4
4
  private tokens;
5
5
  private revokedTokens;
6
- private users;
7
6
  private simulateLatency;
8
7
  private shouldFailAuth;
9
8
  private tokenCounter;
9
+ private currentToken;
10
10
  constructor(options?: {
11
11
  simulateLatency?: number;
12
12
  shouldFailAuth?: boolean;
@@ -15,16 +15,22 @@ export declare class MockAuthAdapter implements IAuthAdapter {
15
15
  generateToken(payload: TokenPayload): Promise<string>;
16
16
  refreshToken(token: string): Promise<string>;
17
17
  revokeToken(token: string): Promise<void>;
18
- authenticate(credentials: Credentials): Promise<AuthResult>;
18
+ getCurrentToken(): string | null;
19
19
  isAuthRequired(): boolean;
20
20
  getAuthTimeout(): number;
21
- getSupportedCredentialTypes(): CredentialType[];
22
21
  private simulateDelay;
23
- addUser(username: string, password: string, payload: TokenPayload): void;
24
- removeUser(username: string): void;
22
+ /**
23
+ * Create and store a test token for a user
24
+ */
25
+ createTestToken(userId: string, options?: {
26
+ permissions?: string[];
27
+ metadata?: Record<string, unknown>;
28
+ expiresIn?: number;
29
+ }): Promise<string>;
25
30
  getTokenCount(): number;
26
31
  getRevokedTokenCount(): number;
27
32
  clearTokens(): void;
28
33
  setFailAuth(fail: boolean): void;
34
+ setCurrentToken(token: string | null): void;
29
35
  }
30
36
  //# sourceMappingURL=MockAuthAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MockAuthAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/mock/MockAuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,cAAc,EACf,MAAM,sBAAsB,CAAC;AAE9B,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,KAAK,CAAuE;IACpF,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,YAAY,CAAa;gBAErB,OAAO,CAAC,EAAE;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B;IAoBK,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAyBnD,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBrD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB5C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWzC,YAAY,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAwGjE,cAAc,IAAI,OAAO;IAIzB,cAAc,IAAI,MAAM;IAIxB,2BAA2B,IAAI,cAAc,EAAE;YAKjC,aAAa;IAM3B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAIxE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIlC,aAAa,IAAI,MAAM;IAIvB,oBAAoB,IAAI,MAAM;IAI9B,WAAW,IAAI,IAAI;IAKnB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;CAGjC"}
1
+ {"version":3,"file":"MockAuthAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/mock/MockAuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,YAAY,CAAuB;gBAE/B,OAAO,CAAC,EAAE;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B;IAKK,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAyBnD,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBrD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB5C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/C,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC,cAAc,IAAI,OAAO;IAIzB,cAAc,IAAI,MAAM;YAKV,aAAa;IAM3B;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAC9C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,MAAM,CAAC;IAYnB,aAAa,IAAI,MAAM;IAIvB,oBAAoB,IAAI,MAAM;IAI9B,WAAW,IAAI,IAAI;IAMnB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIhC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;CAG5C"}
@@ -5,25 +5,12 @@ class MockAuthAdapter {
5
5
  constructor(options) {
6
6
  this.tokens = new Map();
7
7
  this.revokedTokens = new Set();
8
- this.users = new Map();
9
8
  this.simulateLatency = 0;
10
9
  this.shouldFailAuth = false;
11
10
  this.tokenCounter = 0;
11
+ this.currentToken = null;
12
12
  this.simulateLatency = options?.simulateLatency ?? 0;
13
13
  this.shouldFailAuth = options?.shouldFailAuth ?? false;
14
- // Add some default test users
15
- this.addUser('testuser', 'password123', {
16
- userId: 'user-1',
17
- email: 'test@example.com',
18
- username: 'testuser',
19
- permissions: ['read', 'write']
20
- });
21
- this.addUser('admin', 'admin123', {
22
- userId: 'user-admin',
23
- email: 'admin@example.com',
24
- username: 'admin',
25
- permissions: ['read', 'write', 'admin']
26
- });
27
14
  }
28
15
  async validateToken(token) {
29
16
  await this.simulateDelay();
@@ -78,119 +65,34 @@ class MockAuthAdapter {
78
65
  this.tokens.delete(token);
79
66
  this.revokedTokens.add(token);
80
67
  }
81
- async authenticate(credentials) {
82
- await this.simulateDelay();
83
- if (this.shouldFailAuth) {
84
- return {
85
- success: false,
86
- error: 'Mock authentication failed'
87
- };
88
- }
89
- switch (credentials.type) {
90
- case 'password': {
91
- if (!credentials.username || !credentials.password) {
92
- return {
93
- success: false,
94
- error: 'Username and password required'
95
- };
96
- }
97
- const user = this.users.get(credentials.username);
98
- if (!user || user.password !== credentials.password) {
99
- return {
100
- success: false,
101
- error: 'Invalid credentials'
102
- };
103
- }
104
- const token = await this.generateToken(user.payload);
105
- const refreshToken = `refresh-${token}`;
106
- this.tokens.set(refreshToken, user.payload);
107
- return {
108
- success: true,
109
- token,
110
- refreshToken,
111
- user: user.payload,
112
- userId: user.payload.userId,
113
- expiresIn: 3600
114
- };
115
- }
116
- case 'token':
117
- case 'jwt':
118
- case 'bearer': {
119
- if (!credentials.token) {
120
- return {
121
- success: false,
122
- error: 'Token required'
123
- };
124
- }
125
- try {
126
- const payload = await this.validateToken(credentials.token);
127
- return {
128
- success: true,
129
- token: credentials.token,
130
- user: payload,
131
- userId: payload.userId,
132
- expiresIn: 3600
133
- };
134
- }
135
- catch (error) {
136
- return {
137
- success: false,
138
- error: error.message
139
- };
140
- }
141
- }
142
- case 'oauth': {
143
- // Simulate OAuth flow
144
- if (!credentials.code) {
145
- return {
146
- success: false,
147
- error: 'OAuth code required'
148
- };
149
- }
150
- // Create a mock OAuth user
151
- const payload = {
152
- userId: `oauth-user-${Date.now()}`,
153
- email: 'oauth@example.com',
154
- username: 'oauthuser',
155
- permissions: ['read', 'write']
156
- };
157
- const token = await this.generateToken(payload);
158
- return {
159
- success: true,
160
- token,
161
- user: payload,
162
- userId: payload.userId,
163
- expiresIn: 3600
164
- };
165
- }
166
- default:
167
- return {
168
- success: false,
169
- error: 'Unsupported credential type'
170
- };
171
- }
68
+ getCurrentToken() {
69
+ return this.currentToken;
172
70
  }
173
- // New methods for enhanced auth interface
174
71
  isAuthRequired() {
175
72
  return false; // Mock adapter doesn't require auth by default
176
73
  }
177
74
  getAuthTimeout() {
178
75
  return 10000; // 10 seconds for testing
179
76
  }
180
- getSupportedCredentialTypes() {
181
- return ['password', 'token', 'jwt', 'bearer', 'oauth'];
182
- }
183
77
  // Test helper methods
184
78
  async simulateDelay() {
185
79
  if (this.simulateLatency > 0) {
186
80
  await new Promise(resolve => setTimeout(resolve, this.simulateLatency));
187
81
  }
188
82
  }
189
- addUser(username, password, payload) {
190
- this.users.set(username, { password, payload });
191
- }
192
- removeUser(username) {
193
- this.users.delete(username);
83
+ /**
84
+ * Create and store a test token for a user
85
+ */
86
+ async createTestToken(userId, options) {
87
+ const payload = {
88
+ userId,
89
+ permissions: options?.permissions ?? ['read', 'write'],
90
+ metadata: options?.metadata,
91
+ expiresAt: options?.expiresIn ? Date.now() + options.expiresIn : undefined
92
+ };
93
+ const token = await this.generateToken(payload);
94
+ this.currentToken = token;
95
+ return token;
194
96
  }
195
97
  getTokenCount() {
196
98
  return this.tokens.size;
@@ -201,9 +103,13 @@ class MockAuthAdapter {
201
103
  clearTokens() {
202
104
  this.tokens.clear();
203
105
  this.revokedTokens.clear();
106
+ this.currentToken = null;
204
107
  }
205
108
  setFailAuth(fail) {
206
109
  this.shouldFailAuth = fail;
207
110
  }
111
+ setCurrentToken(token) {
112
+ this.currentToken = token;
113
+ }
208
114
  }
209
115
  exports.MockAuthAdapter = MockAuthAdapter;
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketServerTransportAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/websocket/WebSocketServerTransportAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EAGb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEhD,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,+BAAgC,YAAW,iBAAiB;IACvE,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,aAAa,CAAgC;IAGrD,OAAO,CAAC,GAAG,CAAC,CAAkB;IAC9B,OAAO,CAAC,SAAS,CAAC,CAAS;IAG3B,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,WAAW,CAAC,CAAkB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAS;IAG/B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,IAAI,CAA8C;IAG1D,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,MAAM,CAAiC;gBAEnC,MAAM,CAAC,EAAE,8BAA8B;IAUnD,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAclC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCjE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,EAAE,IAAI,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC7E,uBAAuB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;YA2BpD,gBAAgB;YA6EhB,mBAAmB;YAuCnB,iBAAiB;IA4E/B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,YAAY;IAMd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA4C3C,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIxC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,QAAQ,IAAI,eAAe;IAI3B,WAAW,IAAI,OAAO;IAKtB,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC,uBAAuB,IAAI,gBAAgB,EAAE;IAI7C,cAAc,IAAI,MAAM;IAIxB,OAAO,IAAI,YAAY,GAAG,aAAa;IAIvC,cAAc,IAAI,OAAO;IAIzB,OAAO,CAAC,UAAU;CAGnB"}
1
+ {"version":3,"file":"WebSocketServerTransportAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/websocket/WebSocketServerTransportAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEhD,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,+BAAgC,YAAW,iBAAiB;IACvE,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,aAAa,CAAgC;IAGrD,OAAO,CAAC,GAAG,CAAC,CAAkB;IAC9B,OAAO,CAAC,SAAS,CAAC,CAAS;IAG3B,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,WAAW,CAAC,CAAkB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAS;IAG/B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,IAAI,CAA8C;IAG1D,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,MAAM,CAAiC;gBAEnC,MAAM,CAAC,EAAE,8BAA8B;IAUnD,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAclC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCjE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,EAAE,IAAI,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC7E,uBAAuB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;YA2BpD,gBAAgB;YA8EhB,mBAAmB;YAuCnB,iBAAiB;IAiF/B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,YAAY;IAMd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA4C3C,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIxC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,QAAQ,IAAI,eAAe;IAI3B,WAAW,IAAI,OAAO;IAKtB,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC,uBAAuB,IAAI,gBAAgB,EAAE;IAI7C,cAAc,IAAI,MAAM;IAIxB,OAAO,IAAI,YAAY,GAAG,aAAa;IAIvC,cAAc,IAAI,OAAO;IAIzB,OAAO,CAAC,UAAU;CAGnB"}
@@ -115,21 +115,22 @@ class WebSocketServerTransportAdapter {
115
115
  }
116
116
  async handleConnection(ws, req) {
117
117
  const clientId = this.generateId();
118
- // Step 1: Try header authentication if auth adapter is available
118
+ // Step 1: Try token authentication via Authorization header
119
119
  let authenticated = false;
120
- let authResult = null;
120
+ let userId;
121
+ let metadata;
121
122
  if (this.authAdapter && req.headers.authorization) {
122
123
  const token = this.extractBearerToken(req.headers.authorization);
123
124
  if (token) {
124
125
  try {
125
- authResult = await this.authAdapter.authenticate({
126
- type: 'bearer',
127
- token: token
128
- });
129
- authenticated = authResult.success;
126
+ const tokenPayload = await this.authAdapter.validateToken(token);
127
+ authenticated = true;
128
+ userId = tokenPayload.userId;
129
+ metadata = tokenPayload.metadata;
130
130
  }
131
131
  catch {
132
- // Header auth failed but don't reject connection
132
+ // Header auth failed but don't reject connection yet
133
+ // Client can still authenticate via message
133
134
  }
134
135
  }
135
136
  }
@@ -138,8 +139,8 @@ class WebSocketServerTransportAdapter {
138
139
  id: clientId,
139
140
  ws,
140
141
  authenticated,
141
- userId: authResult?.userId || (authResult?.user?.userId),
142
- metadata: authResult?.metadata || authResult?.user?.metadata,
142
+ userId,
143
+ metadata,
143
144
  connectedAt: Date.now()
144
145
  };
145
146
  this.clients.set(clientId, client);
@@ -219,70 +220,72 @@ class WebSocketServerTransportAdapter {
219
220
  if (!this.authAdapter) {
220
221
  this.sendToClient(client, {
221
222
  id: this.generateId(),
222
- type: 'auth_error',
223
- payload: { error: 'No auth adapter configured' },
223
+ type: 'auth_result',
224
+ payload: { success: false, error: 'No auth adapter configured' },
225
+ timestamp: Date.now()
226
+ });
227
+ return;
228
+ }
229
+ const payload = message.payload;
230
+ // Token-based authentication only
231
+ if (!payload.token || typeof payload.token !== 'string') {
232
+ this.sendToClient(client, {
233
+ id: this.generateId(),
234
+ type: 'auth_result',
235
+ payload: { success: false, error: 'Token required for authentication' },
224
236
  timestamp: Date.now()
225
237
  });
226
238
  return;
227
239
  }
228
240
  try {
229
- const credentials = message.payload;
230
- const result = await this.authAdapter.authenticate(credentials);
231
- if (result.success) {
232
- // Clear auth timeout
233
- if (client.authTimeout) {
234
- clearTimeout(client.authTimeout);
235
- client.authTimeout = undefined;
236
- }
237
- // Update client state
238
- client.authenticated = true;
239
- client.userId = result.userId || result.user?.userId;
240
- client.metadata = result.metadata || result.user?.metadata;
241
- // Send success response
242
- this.sendToClient(client, {
243
- id: this.generateId(),
244
- type: 'auth_success',
245
- payload: {
246
- userId: client.userId,
247
- metadata: client.metadata
248
- },
249
- timestamp: Date.now()
250
- });
251
- // Notify handlers about authentication
252
- const authMessage = {
253
- id: this.generateId(),
254
- type: 'client_authenticated',
255
- payload: {
256
- clientId: client.id,
257
- userId: client.userId,
258
- metadata: client.metadata
259
- },
260
- timestamp: Date.now()
261
- };
262
- this.messageHandlers.forEach(handler => handler(authMessage));
263
- }
264
- else {
265
- // Send error response
266
- this.sendToClient(client, {
267
- id: this.generateId(),
268
- type: 'auth_error',
269
- payload: { error: result.error || 'Authentication failed' },
270
- timestamp: Date.now()
271
- });
272
- // Optionally close connection
273
- if (this.config.closeOnAuthFailure) {
274
- client.ws.close(1008, 'Authentication failed');
275
- this.clients.delete(client.id);
276
- }
241
+ const tokenPayload = await this.authAdapter.validateToken(payload.token);
242
+ // Clear auth timeout
243
+ if (client.authTimeout) {
244
+ clearTimeout(client.authTimeout);
245
+ client.authTimeout = undefined;
277
246
  }
247
+ // Update client state
248
+ client.authenticated = true;
249
+ client.userId = tokenPayload.userId;
250
+ client.metadata = tokenPayload.metadata;
251
+ // Send success response
252
+ this.sendToClient(client, {
253
+ id: this.generateId(),
254
+ type: 'auth_result',
255
+ payload: {
256
+ success: true,
257
+ userId: client.userId
258
+ },
259
+ timestamp: Date.now()
260
+ });
261
+ // Notify handlers about authentication
262
+ const authMessage = {
263
+ id: this.generateId(),
264
+ type: 'client_authenticated',
265
+ payload: {
266
+ clientId: client.id,
267
+ userId: client.userId,
268
+ metadata: client.metadata
269
+ },
270
+ timestamp: Date.now()
271
+ };
272
+ this.messageHandlers.forEach(handler => handler(authMessage));
278
273
  }
279
274
  catch (error) {
280
275
  this.sendToClient(client, {
281
276
  id: this.generateId(),
282
- type: 'auth_error',
283
- payload: { error: error.message },
277
+ type: 'auth_result',
278
+ payload: {
279
+ success: false,
280
+ error: error.message
281
+ },
284
282
  timestamp: Date.now()
285
283
  });
284
+ // Optionally close connection on auth failure
285
+ if (this.config.closeOnAuthFailure) {
286
+ client.ws.close(1008, 'Authentication failed');
287
+ this.clients.delete(client.id);
288
+ }
286
289
  }
287
290
  }
288
291
  extractBearerToken(authHeader) {
@@ -1,4 +1,4 @@
1
- import type { ConnectionState, Event, RoomState, RoomUser, LockRequest, Lock, Credentials } from '../types/index.js';
1
+ import type { ConnectionState, Event, RoomState, RoomUser, LockRequest, Lock, AuthenticatePayload } from '../types/index.js';
2
2
  import type { ITransportAdapter } from '../abstractions/TransportAdapter.js';
3
3
  import type { IAuthAdapter } from '../abstractions/AuthAdapter.js';
4
4
  import type { IStorageAdapter } from '../abstractions/StorageAdapter.js';
@@ -19,6 +19,12 @@ export interface ClientEvents {
19
19
  connected: {
20
20
  url: string;
21
21
  };
22
+ authenticated: {
23
+ userId: string;
24
+ };
25
+ authentication_failed: {
26
+ error: string;
27
+ };
22
28
  disconnected: {
23
29
  code: number;
24
30
  reason: string;
@@ -71,11 +77,29 @@ export declare class BaseClient extends TypedEventEmitter<ClientEvents> {
71
77
  private reconnectAttempts;
72
78
  private reconnectTimer;
73
79
  private lastConnectionUrl;
74
- private lastCredentials;
80
+ private lastToken;
75
81
  constructor(config: ClientConfig);
76
- connect(url: string, credentials?: Credentials): Promise<void>;
82
+ /**
83
+ * Connect to the server with an optional authentication token.
84
+ *
85
+ * @param url The WebSocket URL to connect to
86
+ * @param token Optional JWT token for authentication
87
+ */
88
+ connect(url: string, token?: string): Promise<void>;
77
89
  disconnect(): Promise<void>;
78
90
  reconnect(): Promise<void>;
91
+ /**
92
+ * Send an authenticate message to the server with the current token.
93
+ * This must be called after connect() to complete the authentication handshake.
94
+ *
95
+ * @param options Optional authentication options including deviceId and metadata
96
+ * @throws Error if client is not connected or no auth token is available
97
+ */
98
+ authenticate(options?: Omit<AuthenticatePayload, 'token'>): Promise<void>;
99
+ /**
100
+ * Check if the client has an auth token available.
101
+ */
102
+ hasAuthToken(): boolean;
79
103
  joinRoom(roomId: string): Promise<void>;
80
104
  leaveRoom(): Promise<void>;
81
105
  broadcast(event: Event): Promise<void>;
@@ -89,6 +113,7 @@ export declare class BaseClient extends TypedEventEmitter<ClientEvents> {
89
113
  private handleMessage;
90
114
  private handleError;
91
115
  private handleClose;
116
+ private handleAuthResult;
92
117
  private handleRoomJoined;
93
118
  private handleRoomLeft;
94
119
  private handleEventBroadcast;
@@ -1 +1 @@
1
- {"version":3,"file":"BaseClient.d.ts","sourceRoot":"","sources":["../../src/client/BaseClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BaseClient.d.ts","sourceRoot":"","sources":["../../src/client/BaseClient.ts"],"names":[],"mappings":"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"}
@@ -15,7 +15,7 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
15
15
  this.reconnectAttempts = 0;
16
16
  this.reconnectTimer = null;
17
17
  this.lastConnectionUrl = null;
18
- this.lastCredentials = null;
18
+ this.lastToken = null;
19
19
  this.config = config;
20
20
  this.transport = config.transport;
21
21
  this.auth = config.auth;
@@ -26,43 +26,41 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
26
26
  this.transport.onClose(this.handleClose.bind(this));
27
27
  }
28
28
  // Connection Management
29
- async connect(url, credentials) {
29
+ /**
30
+ * Connect to the server with an optional authentication token.
31
+ *
32
+ * @param url The WebSocket URL to connect to
33
+ * @param token Optional JWT token for authentication
34
+ */
35
+ async connect(url, token) {
30
36
  if (this.connectionState !== 'disconnected') {
31
37
  throw new Error('Client is already connected or connecting');
32
38
  }
33
39
  this.connectionState = 'connecting';
34
40
  this.lastConnectionUrl = url;
35
- this.lastCredentials = credentials || null;
41
+ this.lastToken = token || null;
36
42
  try {
37
- let tokenToApply = null;
38
- // Authenticate if credentials provided and auth adapter available
39
- if (credentials && this.auth) {
40
- const authResult = await this.auth.authenticate(credentials);
41
- if (authResult.success && authResult.token) {
42
- this.authToken = authResult.token;
43
- this.userId = authResult.user?.userId || authResult.userId || '';
44
- tokenToApply = authResult.token;
45
- }
43
+ // Use provided token or try to get existing token from auth adapter
44
+ let tokenToApply = token || null;
45
+ if (!tokenToApply && this.auth && typeof this.auth.getCurrentToken === 'function') {
46
+ tokenToApply = this.auth.getCurrentToken();
46
47
  }
47
- // If no credentials but auth adapter exists, try to get existing token
48
- else if (this.auth && typeof this.auth.getCurrentToken === 'function') {
49
- const currentToken = this.auth.getCurrentToken();
50
- if (currentToken) {
51
- this.authToken = currentToken;
52
- tokenToApply = currentToken;
53
- // Try to validate and get user info from token
48
+ if (tokenToApply) {
49
+ this.authToken = tokenToApply;
50
+ // Try to validate and get user info from token
51
+ if (this.auth) {
54
52
  try {
55
- const payload = await this.auth.validateToken(currentToken);
53
+ const payload = await this.auth.validateToken(tokenToApply);
56
54
  this.userId = payload.userId;
57
55
  }
58
56
  catch {
59
- // Token validation failed, but still try to use it
57
+ // Token validation failed locally, server will validate
60
58
  }
61
59
  }
62
- }
63
- // Apply token to transport if we have one and transport supports it
64
- if (tokenToApply && typeof this.transport.setAuthToken === 'function') {
65
- this.transport.setAuthToken(tokenToApply);
60
+ // Apply token to transport if it supports it
61
+ if (typeof this.transport.setAuthToken === 'function') {
62
+ this.transport.setAuthToken(tokenToApply);
63
+ }
66
64
  }
67
65
  const options = {
68
66
  url,
@@ -113,7 +111,41 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
113
111
  if (this.connectionState !== 'disconnected') {
114
112
  await this.disconnect();
115
113
  }
116
- await this.connect(this.lastConnectionUrl, this.lastCredentials || undefined);
114
+ await this.connect(this.lastConnectionUrl, this.lastToken || undefined);
115
+ }
116
+ // Authentication
117
+ /**
118
+ * Send an authenticate message to the server with the current token.
119
+ * This must be called after connect() to complete the authentication handshake.
120
+ *
121
+ * @param options Optional authentication options including deviceId and metadata
122
+ * @throws Error if client is not connected or no auth token is available
123
+ */
124
+ async authenticate(options) {
125
+ if (this.connectionState !== 'connected') {
126
+ throw new Error('Client must be connected to authenticate');
127
+ }
128
+ if (!this.authToken) {
129
+ throw new Error('No auth token available. Connect with credentials first.');
130
+ }
131
+ const payload = {
132
+ token: this.authToken,
133
+ ...options
134
+ };
135
+ const message = {
136
+ id: this.generateId(),
137
+ type: 'authenticate',
138
+ payload,
139
+ timestamp: Date.now()
140
+ };
141
+ await this.transport.send(message);
142
+ // Response will be handled in handleMessage via auth_result
143
+ }
144
+ /**
145
+ * Check if the client has an auth token available.
146
+ */
147
+ hasAuthToken() {
148
+ return this.authToken !== null;
117
149
  }
118
150
  // Room Management
119
151
  async joinRoom(roomId) {
@@ -205,6 +237,9 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
205
237
  async handleMessage(message) {
206
238
  try {
207
239
  switch (message.type) {
240
+ case 'auth_result':
241
+ await this.handleAuthResult(message.payload);
242
+ break;
208
243
  case 'room_joined':
209
244
  await this.handleRoomJoined(message.payload);
210
245
  break;
@@ -250,6 +285,17 @@ class BaseClient extends EventEmitter_js_1.TypedEventEmitter {
250
285
  }
251
286
  }
252
287
  }
288
+ async handleAuthResult(payload) {
289
+ if (payload.success) {
290
+ if (payload.userId) {
291
+ this.userId = payload.userId;
292
+ }
293
+ await this.emit('authenticated', { userId: this.userId || '' });
294
+ }
295
+ else {
296
+ await this.emit('authentication_failed', { error: payload.error || 'Authentication failed' });
297
+ }
298
+ }
253
299
  async handleRoomJoined(payload) {
254
300
  this.currentRoomId = payload.roomId;
255
301
  // Deserialize the plain objects back to Maps
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { EventType, BaseEvent, FileAction, FileChangeEvent, GitStatusEvent, CommitEvent, BranchChangeEvent, CursorPositionEvent, Event, TokenPayload, AuthResult, CredentialType, OAuthProvider, Credentials, JWTConfig, OAuthConfig, AuthProvider, RoomPermission, Room, RoomUser, UserStatus, RoomState, RoomConfig, LockType, LockPriority, Lock, LockRequest, LockQueueItem, LockState, ConnectionState, ConnectionOptions, Message, MessageHandler, ErrorHandler, CloseHandler, ExperimentalFeatureConfig, ClientPredicate, BroadcastResult, BroadcastOptions, ExperimentalUsageEvent, ExperimentalFeatureError, PresenceStatus, DeviceInfo, UserPresence, PresenceConfig, PresenceChangeEvent, ActivityUpdate } from './types/index.js';
1
+ export { EventType, BaseEvent, FileAction, FileChangeEvent, GitStatusEvent, CommitEvent, BranchChangeEvent, CursorPositionEvent, Event, TokenPayload, AuthResult, JWTConfig, AuthenticatePayload, AuthenticateResult, RoomPermission, Room, RoomUser, UserStatus, RoomState, RoomConfig, LockType, LockPriority, Lock, LockRequest, LockQueueItem, LockState, ConnectionState, ConnectionOptions, Message, MessageHandler, ErrorHandler, CloseHandler, ExperimentalFeatureConfig, ClientPredicate, BroadcastResult, BroadcastOptions, ExperimentalUsageEvent, ExperimentalFeatureError, PresenceStatus, DeviceInfo, UserPresence, PresenceConfig, PresenceChangeEvent, ActivityUpdate } from './types/index.js';
2
2
  export { ITransportAdapter, IStorageAdapter, StorageOperation, IAuthAdapter, TypedEventEmitter, EventListener, UnsubscribeFn, RoomManager, LockManager, DefaultRoomManager, DefaultLockManager, PresenceManager, DefaultPresenceManager, PresenceExtension, ExtendedUserPresence } from './abstractions/index.js';
3
3
  export { MockTransportAdapter, MockStorageAdapter, MockAuthAdapter } from './adapters/mock/index.js';
4
4
  export { WebSocketServerTransportAdapter, type WebSocketServerTransportConfig, WebSocketClientTransportAdapter, type WebSocketClientConfig } from './adapters/websocket/index.js';