@codeguide/core 0.0.28 → 0.0.29
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/__tests__/services/usage/usage-service.test.ts +442 -83
- package/codeguide.ts +3 -0
- package/dist/codeguide.d.ts +2 -1
- package/dist/codeguide.js +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/services/base/base-service.d.ts +21 -0
- package/dist/services/base/base-service.js +114 -0
- package/dist/services/codespace/codespace-service.d.ts +55 -1
- package/dist/services/codespace/codespace-service.js +257 -0
- package/dist/services/codespace/codespace-types.d.ts +192 -12
- package/dist/services/codespace/index.d.ts +1 -1
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +4 -1
- package/dist/services/projects/project-types.d.ts +66 -32
- package/dist/services/starter-kits/index.d.ts +2 -0
- package/dist/services/starter-kits/index.js +20 -0
- package/dist/services/starter-kits/starter-kits-service.d.ts +13 -0
- package/dist/services/starter-kits/starter-kits-service.js +27 -0
- package/dist/services/starter-kits/starter-kits-types.d.ts +34 -0
- package/dist/services/starter-kits/starter-kits-types.js +2 -0
- package/dist/services/tasks/task-service.d.ts +2 -1
- package/dist/services/tasks/task-service.js +8 -0
- package/dist/services/tasks/task-types.d.ts +26 -7
- package/dist/services/usage/usage-service.d.ts +5 -2
- package/dist/services/usage/usage-service.js +58 -9
- package/dist/services/usage/usage-types.d.ts +150 -26
- package/docs/.vitepress/README.md +51 -0
- package/docs/.vitepress/config.ts +139 -0
- package/docs/.vitepress/theme/custom.css +80 -0
- package/docs/.vitepress/theme/index.ts +13 -0
- package/docs/.vitepress/tsconfig.json +19 -0
- package/docs/QUICKSTART.md +77 -0
- package/docs/README.md +134 -0
- package/docs/README_SETUP.md +46 -0
- package/docs/authentication.md +351 -0
- package/docs/codeguide-client.md +350 -0
- package/docs/codespace-models.md +1004 -0
- package/docs/codespace-service.md +444 -0
- package/docs/index.md +135 -0
- package/docs/package.json +14 -0
- package/docs/projects-service.md +688 -0
- package/docs/security-keys-service.md +773 -0
- package/docs/starter-kits-service.md +249 -0
- package/docs/task-service.md +955 -0
- package/docs/testsprite_tests/TC001_Homepage_Load_and_Hero_Section_Display.py +70 -0
- package/docs/testsprite_tests/TC002_Sidebar_Navigation_ExpandCollapse_Functionality.py +73 -0
- package/docs/testsprite_tests/TC003_Full_Text_Local_Search_with_Keyboard_Shortcut.py +90 -0
- package/docs/testsprite_tests/TC004_Dark_Mode_Toggle_and_Persistence.py +73 -0
- package/docs/testsprite_tests/TC005_Mobile_Responsiveness_and_Touch_Navigation.py +113 -0
- package/docs/testsprite_tests/TC006_GitHub_Integration_Edit_this_page_Links.py +73 -0
- package/docs/testsprite_tests/TC007_Syntax_Highlighting_and_Code_Copy_Functionality.py +73 -0
- package/docs/testsprite_tests/TC008_Auto_Generated_Table_of_Contents_Accuracy.py +73 -0
- package/docs/testsprite_tests/TC009_SEO_and_Content_Discoverability_Verification.py +73 -0
- package/docs/testsprite_tests/TC010_Accessibility_Compliance_WCAG_AA.py +73 -0
- package/docs/testsprite_tests/TC011_Local_Development_Workflow_Build_and_Hot_Reload.py +74 -0
- package/docs/testsprite_tests/TC012_Performance_Metrics_Compliance.py +73 -0
- package/docs/testsprite_tests/standard_prd.json +122 -0
- package/docs/testsprite_tests/testsprite-mcp-test-report.html +2508 -0
- package/docs/testsprite_tests/testsprite-mcp-test-report.md +273 -0
- package/docs/testsprite_tests/testsprite_frontend_test_plan.json +390 -0
- package/docs/usage-service.md +291 -1
- package/index.ts +11 -3
- package/package.json +16 -2
- package/plans/CODESPACE_LOGS_STREAMING_GUIDE.md +320 -0
- package/plans/CODESPACE_TASK_LOGS_API_COMPLETE_GUIDE.md +821 -0
- package/services/base/base-service.ts +130 -0
- package/services/codespace/codespace-service.ts +337 -0
- package/services/codespace/codespace-types.ts +262 -13
- package/services/codespace/index.ts +16 -1
- package/services/index.ts +2 -0
- package/services/projects/README.md +107 -34
- package/services/projects/project-types.ts +69 -32
- package/services/starter-kits/index.ts +2 -0
- package/services/starter-kits/starter-kits-service.ts +33 -0
- package/services/starter-kits/starter-kits-types.ts +38 -0
- package/services/tasks/task-service.ts +10 -0
- package/services/tasks/task-types.ts +29 -7
- package/services/usage/usage-service.ts +59 -10
- package/services/usage/usage-types.ts +178 -27
|
@@ -0,0 +1,773 @@
|
|
|
1
|
+
# Security Keys Service
|
|
2
|
+
|
|
3
|
+
The Security Keys Service provides methods for securely managing provider API keys (OpenAI, Anthropic, etc.) and GitHub tokens. All keys are encrypted and stored securely.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Security Keys Service allows you to:
|
|
8
|
+
- Store and manage provider API keys (OpenAI, Anthropic, etc.)
|
|
9
|
+
- Store and manage GitHub personal access tokens
|
|
10
|
+
- Retrieve keys (with optional reveal option)
|
|
11
|
+
- Revoke/delete stored keys
|
|
12
|
+
- List all stored keys
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
### Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @codeguide/core
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Basic Initialization
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { CodeGuide } from '@codeguide/core'
|
|
26
|
+
|
|
27
|
+
const codeguide = new CodeGuide({
|
|
28
|
+
baseUrl: 'https://api.codeguide.ai',
|
|
29
|
+
databaseApiKey: 'sk_your_database_api_key',
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// Access the security keys service
|
|
33
|
+
const securityKeys = codeguide.securityKeys
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Methods Overview
|
|
37
|
+
|
|
38
|
+
### Provider API Keys
|
|
39
|
+
|
|
40
|
+
| Method | Description | Endpoint |
|
|
41
|
+
|--------|-------------|----------|
|
|
42
|
+
| `createProviderAPIKey()` | Save a provider API key | `POST /security-keys/provider-api-key` |
|
|
43
|
+
| `getProviderAPIKey()` | Get a provider API key | `GET /security-keys/provider-api-key/{provider_key}` |
|
|
44
|
+
| `listProviderAPIKeys()` | List all provider API keys | `GET /security-keys/provider-api-keys` |
|
|
45
|
+
| `revokeProviderAPIKey()` | Delete a provider API key | `DELETE /security-keys/provider-api-key/{provider_key}` |
|
|
46
|
+
|
|
47
|
+
### GitHub Tokens
|
|
48
|
+
|
|
49
|
+
| Method | Description | Endpoint |
|
|
50
|
+
|--------|-------------|----------|
|
|
51
|
+
| `createGitHubToken()` | Save a GitHub token | `POST /security-keys/github-token` |
|
|
52
|
+
| `getGitHubToken()` | Get the GitHub token | `GET /security-keys/github-token` |
|
|
53
|
+
| `revokeGitHubToken()` | Delete the GitHub token | `DELETE /security-keys/github-token` |
|
|
54
|
+
|
|
55
|
+
## Detailed Method Documentation
|
|
56
|
+
|
|
57
|
+
### Provider API Keys
|
|
58
|
+
|
|
59
|
+
#### 1. createProviderAPIKey()
|
|
60
|
+
|
|
61
|
+
Saves a new provider API key. The key is encrypted and stored securely.
|
|
62
|
+
|
|
63
|
+
#### Signature
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
async createProviderAPIKey(request: CreateProviderAPIKeyRequest): Promise<CreateProviderAPIKeyResponse>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Parameters
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
interface CreateProviderAPIKeyRequest {
|
|
73
|
+
provider_key: string // Required: Provider key (e.g., 'openai', 'anthropic')
|
|
74
|
+
api_key: string // Required: The API key (minimum 10 characters)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### Returns
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface CreateProviderAPIKeyResponse {
|
|
82
|
+
status: 'success'
|
|
83
|
+
data: ProviderAPIKeyData
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface ProviderAPIKeyData {
|
|
87
|
+
id: string
|
|
88
|
+
created_at: string
|
|
89
|
+
user_id: string
|
|
90
|
+
name: string
|
|
91
|
+
displayed_name: string
|
|
92
|
+
value_masked: string // Masked version of the key
|
|
93
|
+
value?: string // Only included when reveal=true
|
|
94
|
+
object_value: {
|
|
95
|
+
provider_id: string
|
|
96
|
+
}
|
|
97
|
+
encryption: string
|
|
98
|
+
key_version: string
|
|
99
|
+
provider_id: string
|
|
100
|
+
provider_name: string
|
|
101
|
+
provider_key: string
|
|
102
|
+
provider_logo_src?: string // Only in list endpoint
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### Validation
|
|
107
|
+
|
|
108
|
+
- `provider_key` is required
|
|
109
|
+
- `api_key` is required and must be at least 10 characters long
|
|
110
|
+
- Provider must exist in the system
|
|
111
|
+
|
|
112
|
+
#### Example
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// Store an OpenAI API key
|
|
116
|
+
const response = await codeguide.securityKeys.createProviderAPIKey({
|
|
117
|
+
provider_key: 'openai',
|
|
118
|
+
api_key: 'sk-your-openai-api-key-here',
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
console.log(`Stored key for ${response.data.provider_name}`)
|
|
122
|
+
console.log(`Masked value: ${response.data.value_masked}`)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
#### 2. getProviderAPIKey()
|
|
126
|
+
|
|
127
|
+
Retrieves a provider API key by provider key.
|
|
128
|
+
|
|
129
|
+
#### Signature
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
async getProviderAPIKey(providerKey: string, reveal: boolean = false): Promise<GetProviderAPIKeyResponse>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### Parameters
|
|
136
|
+
|
|
137
|
+
- `providerKey` (string, required): The provider key (e.g., 'openai', 'anthropic')
|
|
138
|
+
- `reveal` (boolean, optional): Whether to reveal the actual API key (default: false)
|
|
139
|
+
|
|
140
|
+
#### Returns
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
interface GetProviderAPIKeyResponse {
|
|
144
|
+
status: 'success'
|
|
145
|
+
data: ProviderAPIKeyData
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Example
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Get masked key (default)
|
|
153
|
+
const masked = await codeguide.securityKeys.getProviderAPIKey('openai')
|
|
154
|
+
console.log(`Masked key: ${masked.data.value_masked}`)
|
|
155
|
+
|
|
156
|
+
// Get revealed key
|
|
157
|
+
const revealed = await codeguide.securityKeys.getProviderAPIKey('openai', true)
|
|
158
|
+
console.log(`Actual key: ${revealed.data.value}`) // Only if reveal=true
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### 3. listProviderAPIKeys()
|
|
162
|
+
|
|
163
|
+
Lists all stored provider API keys.
|
|
164
|
+
|
|
165
|
+
#### Signature
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
async listProviderAPIKeys(reveal: boolean = false): Promise<ListProviderAPIKeysResponse>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### Parameters
|
|
172
|
+
|
|
173
|
+
- `reveal` (boolean, optional): Whether to reveal the actual API keys (default: false)
|
|
174
|
+
|
|
175
|
+
#### Returns
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
interface ListProviderAPIKeysResponse {
|
|
179
|
+
status: 'success'
|
|
180
|
+
data: ProviderAPIKeyData[]
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### Example
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// List all keys (masked)
|
|
188
|
+
const keys = await codeguide.securityKeys.listProviderAPIKeys()
|
|
189
|
+
|
|
190
|
+
console.log(`Found ${keys.data.length} provider keys:`)
|
|
191
|
+
keys.data.forEach(key => {
|
|
192
|
+
console.log(`- ${key.provider_name} (${key.provider_key})`)
|
|
193
|
+
console.log(` Masked: ${key.value_masked}`)
|
|
194
|
+
if (key.provider_logo_src) {
|
|
195
|
+
console.log(` Logo: ${key.provider_logo_src}`)
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// List with revealed keys (use with caution)
|
|
200
|
+
const revealedKeys = await codeguide.securityKeys.listProviderAPIKeys(true)
|
|
201
|
+
revealedKeys.data.forEach(key => {
|
|
202
|
+
console.log(`${key.provider_name}: ${key.value}`)
|
|
203
|
+
})
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### 4. revokeProviderAPIKey()
|
|
207
|
+
|
|
208
|
+
Deletes a provider API key.
|
|
209
|
+
|
|
210
|
+
#### Signature
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
async revokeProviderAPIKey(providerKey: string): Promise<RevokeProviderAPIKeyResponse>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### Parameters
|
|
217
|
+
|
|
218
|
+
- `providerKey` (string, required): The provider key to delete
|
|
219
|
+
|
|
220
|
+
#### Returns
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
interface RevokeProviderAPIKeyResponse {
|
|
224
|
+
status: string
|
|
225
|
+
message: string
|
|
226
|
+
revoked_provider_id: string
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### Example
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const result = await codeguide.securityKeys.revokeProviderAPIKey('openai')
|
|
234
|
+
|
|
235
|
+
console.log(result.status) // "success"
|
|
236
|
+
console.log(result.message) // "Provider API key revoked successfully"
|
|
237
|
+
console.log(`Revoked provider ID: ${result.revoked_provider_id}`)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### GitHub Tokens
|
|
241
|
+
|
|
242
|
+
#### 5. createGitHubToken()
|
|
243
|
+
|
|
244
|
+
Saves a GitHub personal access token. The token is encrypted and stored securely.
|
|
245
|
+
|
|
246
|
+
#### Signature
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
async createGitHubToken(request: CreateGitHubTokenRequest): Promise<CreateGitHubTokenResponse>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
#### Parameters
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
interface CreateGitHubTokenRequest {
|
|
256
|
+
github_token: string // Required: GitHub personal access token
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### Returns
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
interface CreateGitHubTokenResponse {
|
|
264
|
+
status: 'success'
|
|
265
|
+
data: GitHubTokenData
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
interface GitHubTokenData {
|
|
269
|
+
id: string
|
|
270
|
+
created_at: string
|
|
271
|
+
user_id: string
|
|
272
|
+
name: string
|
|
273
|
+
displayed_name: string
|
|
274
|
+
value_masked: string // Masked version of the token
|
|
275
|
+
value?: string // Only included when reveal=true
|
|
276
|
+
object_value: {
|
|
277
|
+
token_type: string
|
|
278
|
+
}
|
|
279
|
+
encryption: string
|
|
280
|
+
key_version: string
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### Validation
|
|
285
|
+
|
|
286
|
+
- `github_token` is required
|
|
287
|
+
- Token must be a valid GitHub token format:
|
|
288
|
+
- Prefixes: `ghp_`, `gho_`, `ghu_`, `ghs_`, `ghr_`, or `github_pat_`
|
|
289
|
+
- Minimum length: 40 characters
|
|
290
|
+
- Token is validated with GitHub API
|
|
291
|
+
|
|
292
|
+
#### Example
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// Store a GitHub token
|
|
296
|
+
const response = await codeguide.securityKeys.createGitHubToken({
|
|
297
|
+
github_token: 'ghp_your_github_personal_access_token_here',
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
console.log(`GitHub token stored`)
|
|
301
|
+
console.log(`Masked value: ${response.data.value_masked}`)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
#### 6. getGitHubToken()
|
|
305
|
+
|
|
306
|
+
Retrieves the stored GitHub token.
|
|
307
|
+
|
|
308
|
+
#### Signature
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
async getGitHubToken(reveal: boolean = false): Promise<GetGitHubTokenResponse>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
#### Parameters
|
|
315
|
+
|
|
316
|
+
- `reveal` (boolean, optional): Whether to reveal the actual token (default: false)
|
|
317
|
+
|
|
318
|
+
#### Returns
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
interface GetGitHubTokenResponse {
|
|
322
|
+
status: 'success'
|
|
323
|
+
data: GitHubTokenData
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### Example
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
// Get masked token (default)
|
|
331
|
+
const masked = await codeguide.securityKeys.getGitHubToken()
|
|
332
|
+
console.log(`Masked token: ${masked.data.value_masked}`)
|
|
333
|
+
|
|
334
|
+
// Get revealed token
|
|
335
|
+
const revealed = await codeguide.securityKeys.getGitHubToken(true)
|
|
336
|
+
console.log(`Actual token: ${revealed.data.value}`) // Only if reveal=true
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
#### 7. revokeGitHubToken()
|
|
340
|
+
|
|
341
|
+
Deletes the stored GitHub token.
|
|
342
|
+
|
|
343
|
+
#### Signature
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
async revokeGitHubToken(): Promise<RevokeGitHubTokenResponse>
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### Returns
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
interface RevokeGitHubTokenResponse {
|
|
353
|
+
status: string
|
|
354
|
+
message: string
|
|
355
|
+
revoked_at: string
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### Example
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
const result = await codeguide.securityKeys.revokeGitHubToken()
|
|
363
|
+
|
|
364
|
+
console.log(result.status) // "success"
|
|
365
|
+
console.log(result.message) // "GitHub token revoked successfully"
|
|
366
|
+
console.log(`Revoked at: ${result.revoked_at}`)
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Error Handling
|
|
370
|
+
|
|
371
|
+
### Common Errors
|
|
372
|
+
|
|
373
|
+
#### Provider Not Found
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
try {
|
|
377
|
+
await codeguide.securityKeys.createProviderAPIKey({
|
|
378
|
+
provider_key: 'invalid_provider',
|
|
379
|
+
api_key: 'sk-key-here',
|
|
380
|
+
})
|
|
381
|
+
} catch (error) {
|
|
382
|
+
if (error.message.includes('not found')) {
|
|
383
|
+
console.error('Provider not found. Please choose a valid provider.')
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### Duplicate Key
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
try {
|
|
392
|
+
await codeguide.securityKeys.createProviderAPIKey({
|
|
393
|
+
provider_key: 'openai',
|
|
394
|
+
api_key: 'sk-key-here',
|
|
395
|
+
})
|
|
396
|
+
} catch (error) {
|
|
397
|
+
if (error.message.includes('already exists')) {
|
|
398
|
+
console.error('API key for this provider already exists. Use update endpoint to change it.')
|
|
399
|
+
// Or revoke the existing key first
|
|
400
|
+
await codeguide.securityKeys.revokeProviderAPIKey('openai')
|
|
401
|
+
// Then create the new one
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
#### Invalid GitHub Token Format
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
try {
|
|
410
|
+
await codeguide.securityKeys.createGitHubToken({
|
|
411
|
+
github_token: 'invalid-token',
|
|
412
|
+
})
|
|
413
|
+
} catch (error) {
|
|
414
|
+
if (error.message.includes('Invalid GitHub token format')) {
|
|
415
|
+
console.error('Token must start with ghp_, gho_, ghu_, ghs_, ghr_, or github_pat_')
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
#### Key Not Found
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
try {
|
|
424
|
+
await codeguide.securityKeys.getProviderAPIKey('openai')
|
|
425
|
+
} catch (error) {
|
|
426
|
+
if (error.message.includes('not found')) {
|
|
427
|
+
console.error('No API key found for this provider')
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
#### Authentication Errors
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
try {
|
|
436
|
+
await codeguide.securityKeys.listProviderAPIKeys()
|
|
437
|
+
} catch (error) {
|
|
438
|
+
if (error.message.includes('401') || error.message.includes('Authentication')) {
|
|
439
|
+
console.error('Authentication failed. Check your API credentials.')
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
## Complete Examples
|
|
445
|
+
|
|
446
|
+
### Example 1: Managing Provider API Keys
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
import { CodeGuide } from '@codeguide/core'
|
|
450
|
+
|
|
451
|
+
const codeguide = new CodeGuide({
|
|
452
|
+
baseUrl: 'https://api.codeguide.ai',
|
|
453
|
+
databaseApiKey: process.env.CODEGUIDE_API_KEY!,
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
async function manageProviderKeys() {
|
|
457
|
+
try {
|
|
458
|
+
// 1. Store OpenAI API key
|
|
459
|
+
const openaiKey = await codeguide.securityKeys.createProviderAPIKey({
|
|
460
|
+
provider_key: 'openai',
|
|
461
|
+
api_key: process.env.OPENAI_API_KEY!,
|
|
462
|
+
})
|
|
463
|
+
console.log(`Stored OpenAI key: ${openaiKey.data.value_masked}`)
|
|
464
|
+
|
|
465
|
+
// 2. Store Anthropic API key
|
|
466
|
+
const anthropicKey = await codeguide.securityKeys.createProviderAPIKey({
|
|
467
|
+
provider_key: 'anthropic',
|
|
468
|
+
api_key: process.env.ANTHROPIC_API_KEY!,
|
|
469
|
+
})
|
|
470
|
+
console.log(`Stored Anthropic key: ${anthropicKey.data.value_masked}`)
|
|
471
|
+
|
|
472
|
+
// 3. List all stored keys
|
|
473
|
+
const allKeys = await codeguide.securityKeys.listProviderAPIKeys()
|
|
474
|
+
console.log(`\nStored ${allKeys.data.length} provider keys:`)
|
|
475
|
+
allKeys.data.forEach(key => {
|
|
476
|
+
console.log(`- ${key.provider_name}: ${key.value_masked}`)
|
|
477
|
+
})
|
|
478
|
+
|
|
479
|
+
// 4. Get a specific key (masked)
|
|
480
|
+
const retrieved = await codeguide.securityKeys.getProviderAPIKey('openai')
|
|
481
|
+
console.log(`\nRetrieved OpenAI key: ${retrieved.data.value_masked}`)
|
|
482
|
+
|
|
483
|
+
// 5. Revoke a key
|
|
484
|
+
await codeguide.securityKeys.revokeProviderAPIKey('anthropic')
|
|
485
|
+
console.log('\nAnthropic key revoked')
|
|
486
|
+
} catch (error) {
|
|
487
|
+
console.error('Error:', error.message)
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
manageProviderKeys()
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### Example 2: Managing GitHub Tokens
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
async function manageGitHubToken() {
|
|
498
|
+
try {
|
|
499
|
+
// 1. Store GitHub token
|
|
500
|
+
const token = await codeguide.securityKeys.createGitHubToken({
|
|
501
|
+
github_token: process.env.GITHUB_TOKEN!,
|
|
502
|
+
})
|
|
503
|
+
console.log(`GitHub token stored: ${token.data.value_masked}`)
|
|
504
|
+
|
|
505
|
+
// 2. Retrieve token (masked)
|
|
506
|
+
const retrieved = await codeguide.securityKeys.getGitHubToken()
|
|
507
|
+
console.log(`Retrieved token: ${retrieved.data.value_masked}`)
|
|
508
|
+
|
|
509
|
+
// 3. Use token in a codespace task
|
|
510
|
+
const task = await codeguide.codespace.createCodespaceTaskV2({
|
|
511
|
+
project_id: 'proj_123456',
|
|
512
|
+
task_description: 'Implement new feature',
|
|
513
|
+
github_token: process.env.GITHUB_TOKEN!, // Or retrieve with reveal=true
|
|
514
|
+
})
|
|
515
|
+
|
|
516
|
+
// 4. Revoke token when done
|
|
517
|
+
await codeguide.securityKeys.revokeGitHubToken()
|
|
518
|
+
console.log('GitHub token revoked')
|
|
519
|
+
} catch (error) {
|
|
520
|
+
console.error('Error:', error.message)
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### Example 3: Key Rotation
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
async function rotateProviderKey(providerKey: string, newApiKey: string) {
|
|
529
|
+
try {
|
|
530
|
+
// Check if key exists
|
|
531
|
+
try {
|
|
532
|
+
const existing = await codeguide.securityKeys.getProviderAPIKey(providerKey)
|
|
533
|
+
console.log(`Existing key found: ${existing.data.value_masked}`)
|
|
534
|
+
|
|
535
|
+
// Revoke old key
|
|
536
|
+
await codeguide.securityKeys.revokeProviderAPIKey(providerKey)
|
|
537
|
+
console.log('Old key revoked')
|
|
538
|
+
} catch (error) {
|
|
539
|
+
if (!error.message.includes('not found')) {
|
|
540
|
+
throw error
|
|
541
|
+
}
|
|
542
|
+
console.log('No existing key found')
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Store new key
|
|
546
|
+
const newKey = await codeguide.securityKeys.createProviderAPIKey({
|
|
547
|
+
provider_key: providerKey,
|
|
548
|
+
api_key: newApiKey,
|
|
549
|
+
})
|
|
550
|
+
|
|
551
|
+
console.log(`New key stored: ${newKey.data.value_masked}`)
|
|
552
|
+
return newKey
|
|
553
|
+
} catch (error) {
|
|
554
|
+
console.error('Key rotation failed:', error.message)
|
|
555
|
+
throw error
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Usage
|
|
560
|
+
await rotateProviderKey('openai', process.env.NEW_OPENAI_KEY!)
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Example 4: Security Audit
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
async function securityAudit() {
|
|
567
|
+
try {
|
|
568
|
+
// List all provider keys
|
|
569
|
+
const providerKeys = await codeguide.securityKeys.listProviderAPIKeys()
|
|
570
|
+
console.log(`\nProvider API Keys (${providerKeys.data.length}):`)
|
|
571
|
+
providerKeys.data.forEach(key => {
|
|
572
|
+
console.log(`- ${key.provider_name} (${key.provider_key})`)
|
|
573
|
+
console.log(` Created: ${key.created_at}`)
|
|
574
|
+
console.log(` Masked: ${key.value_masked}`)
|
|
575
|
+
})
|
|
576
|
+
|
|
577
|
+
// Check GitHub token
|
|
578
|
+
try {
|
|
579
|
+
const githubToken = await codeguide.securityKeys.getGitHubToken()
|
|
580
|
+
console.log(`\nGitHub Token:`)
|
|
581
|
+
console.log(` Created: ${githubToken.data.created_at}`)
|
|
582
|
+
console.log(` Masked: ${githubToken.data.value_masked}`)
|
|
583
|
+
} catch (error) {
|
|
584
|
+
if (error.message.includes('not found')) {
|
|
585
|
+
console.log('\nGitHub Token: Not stored')
|
|
586
|
+
} else {
|
|
587
|
+
throw error
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
} catch (error) {
|
|
591
|
+
console.error('Audit failed:', error.message)
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
## Security Best Practices
|
|
597
|
+
|
|
598
|
+
### 1. Never Log Revealed Keys
|
|
599
|
+
|
|
600
|
+
```typescript
|
|
601
|
+
// ❌ Bad: Logging revealed keys
|
|
602
|
+
const key = await codeguide.securityKeys.getProviderAPIKey('openai', true)
|
|
603
|
+
console.log(key.data.value) // Never do this!
|
|
604
|
+
|
|
605
|
+
// ✅ Good: Only log masked values
|
|
606
|
+
const key = await codeguide.securityKeys.getProviderAPIKey('openai')
|
|
607
|
+
console.log(key.data.value_masked) // Safe to log
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
### 2. Use Environment Variables
|
|
611
|
+
|
|
612
|
+
```typescript
|
|
613
|
+
// ✅ Good: Store keys in environment variables
|
|
614
|
+
const key = await codeguide.securityKeys.createProviderAPIKey({
|
|
615
|
+
provider_key: 'openai',
|
|
616
|
+
api_key: process.env.OPENAI_API_KEY!, // From environment
|
|
617
|
+
})
|
|
618
|
+
|
|
619
|
+
// ❌ Bad: Hardcoding keys
|
|
620
|
+
const key = await codeguide.securityKeys.createProviderAPIKey({
|
|
621
|
+
provider_key: 'openai',
|
|
622
|
+
api_key: 'sk-hardcoded-key-here', // Never do this!
|
|
623
|
+
})
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
### 3. Rotate Keys Regularly
|
|
627
|
+
|
|
628
|
+
```typescript
|
|
629
|
+
// Implement key rotation schedule
|
|
630
|
+
async function rotateKeysMonthly() {
|
|
631
|
+
const providers = ['openai', 'anthropic']
|
|
632
|
+
|
|
633
|
+
for (const provider of providers) {
|
|
634
|
+
// Generate new key (implementation depends on provider)
|
|
635
|
+
const newKey = await generateNewKey(provider)
|
|
636
|
+
|
|
637
|
+
// Rotate
|
|
638
|
+
await rotateProviderKey(provider, newKey)
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### 4. Handle Errors Gracefully
|
|
644
|
+
|
|
645
|
+
```typescript
|
|
646
|
+
async function safeGetKey(providerKey: string) {
|
|
647
|
+
try {
|
|
648
|
+
return await codeguide.securityKeys.getProviderAPIKey(providerKey)
|
|
649
|
+
} catch (error) {
|
|
650
|
+
if (error.message.includes('not found')) {
|
|
651
|
+
console.warn(`No key found for ${providerKey}`)
|
|
652
|
+
return null
|
|
653
|
+
}
|
|
654
|
+
throw error
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### 5. Revoke Unused Keys
|
|
660
|
+
|
|
661
|
+
```typescript
|
|
662
|
+
async function cleanupUnusedKeys() {
|
|
663
|
+
const keys = await codeguide.securityKeys.listProviderAPIKeys()
|
|
664
|
+
|
|
665
|
+
// Implement logic to identify unused keys
|
|
666
|
+
const unusedKeys = keys.data.filter(key => {
|
|
667
|
+
// Your logic here
|
|
668
|
+
return false // Placeholder
|
|
669
|
+
})
|
|
670
|
+
|
|
671
|
+
for (const key of unusedKeys) {
|
|
672
|
+
await codeguide.securityKeys.revokeProviderAPIKey(key.provider_key)
|
|
673
|
+
console.log(`Revoked unused key: ${key.provider_key}`)
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
## Type Definitions
|
|
679
|
+
|
|
680
|
+
### Complete Type Reference
|
|
681
|
+
|
|
682
|
+
```typescript
|
|
683
|
+
// Provider API Key Types
|
|
684
|
+
interface CreateProviderAPIKeyRequest {
|
|
685
|
+
provider_key: string
|
|
686
|
+
api_key: string
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
interface ProviderAPIKeyData {
|
|
690
|
+
id: string
|
|
691
|
+
created_at: string
|
|
692
|
+
user_id: string
|
|
693
|
+
name: string
|
|
694
|
+
displayed_name: string
|
|
695
|
+
value_masked: string
|
|
696
|
+
value?: string
|
|
697
|
+
object_value: {
|
|
698
|
+
provider_id: string
|
|
699
|
+
}
|
|
700
|
+
encryption: string
|
|
701
|
+
key_version: string
|
|
702
|
+
provider_id: string
|
|
703
|
+
provider_name: string
|
|
704
|
+
provider_key: string
|
|
705
|
+
provider_logo_src?: string
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// GitHub Token Types
|
|
709
|
+
interface CreateGitHubTokenRequest {
|
|
710
|
+
github_token: string
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
interface GitHubTokenData {
|
|
714
|
+
id: string
|
|
715
|
+
created_at: string
|
|
716
|
+
user_id: string
|
|
717
|
+
name: string
|
|
718
|
+
displayed_name: string
|
|
719
|
+
value_masked: string
|
|
720
|
+
value?: string
|
|
721
|
+
object_value: {
|
|
722
|
+
token_type: string
|
|
723
|
+
}
|
|
724
|
+
encryption: string
|
|
725
|
+
key_version: string
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Response Types
|
|
729
|
+
interface CreateProviderAPIKeyResponse {
|
|
730
|
+
status: 'success'
|
|
731
|
+
data: ProviderAPIKeyData
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
interface GetProviderAPIKeyResponse {
|
|
735
|
+
status: 'success'
|
|
736
|
+
data: ProviderAPIKeyData
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
interface ListProviderAPIKeysResponse {
|
|
740
|
+
status: 'success'
|
|
741
|
+
data: ProviderAPIKeyData[]
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
interface RevokeProviderAPIKeyResponse {
|
|
745
|
+
status: string
|
|
746
|
+
message: string
|
|
747
|
+
revoked_provider_id: string
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
interface CreateGitHubTokenResponse {
|
|
751
|
+
status: 'success'
|
|
752
|
+
data: GitHubTokenData
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
interface GetGitHubTokenResponse {
|
|
756
|
+
status: 'success'
|
|
757
|
+
data: GitHubTokenData
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
interface RevokeGitHubTokenResponse {
|
|
761
|
+
status: string
|
|
762
|
+
message: string
|
|
763
|
+
revoked_at: string
|
|
764
|
+
}
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
## Related Documentation
|
|
768
|
+
|
|
769
|
+
- [CodeGuide Client](./codeguide-client.md) - Client initialization
|
|
770
|
+
- [Authentication](./authentication.md) - Authentication methods
|
|
771
|
+
- [Projects Service](./projects-service.md) - Project management
|
|
772
|
+
- [Codespace Service](./codespace-service.md) - Using keys in codespace tasks
|
|
773
|
+
|