Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
build:
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
create-release:
permissions:
contents: write
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
outputs:
release_id: ${{ steps.create-release.outputs.result }}

Expand Down Expand Up @@ -48,7 +48,7 @@ jobs:
- platform: 'macos-latest'
args: '--target x86_64-apple-darwin'
name: 'macOS (Intel)'
- platform: 'ubuntu-20.04'
- platform: 'ubuntu-22.04'
args: ''
name: 'Linux'
- platform: 'windows-latest'
Expand All @@ -61,7 +61,7 @@ jobs:
uses: actions/checkout@v4

- name: Install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-20.04'
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libssl-dev pkg-config
Expand All @@ -87,7 +87,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: '20'

- name: Enable Corepack
run: corepack enable
Expand Down Expand Up @@ -119,7 +119,7 @@ jobs:
publish-release:
permissions:
contents: write
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
needs: [create-release, build-tauri]

steps:
Expand Down
13 changes: 7 additions & 6 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ on:
pull_request:
branches: [ main ]
schedule:
- cron: '0 0 * * 1' # Weekly on Mondays
- cron: '0 0 * * 1'

jobs:
audit:
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read

steps:
- uses: actions/checkout@v4
Expand All @@ -29,21 +32,19 @@ jobs:

- name: Audit npm packages
run: yarn audit --audit-level moderate
continue-on-error: true

- name: Audit Rust dependencies
run: |
cd src-tauri
cargo audit
continue-on-error: true

- name: Security scan with Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/secrets
p/owasp-top-ten
p/ci
p/rust
p/javascript

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
Expand Down
1 change: 0 additions & 1 deletion components/ApiKeyDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import { useAppStore } from '../lib/store'
import type { ApiKey } from '../lib/store'
import ProjectPathDisplay from './ProjectPathDisplay'
import { TauriAPI } from '../lib/tauri-api'
import { nativeStorageService } from '../lib/services/nativeStorageService'
import ConfigGenerationModal from './modals/ConfigGenerationModal'
import ApiDocumentationSection from './docs/ApiDocumentationSection'

Expand Down
9 changes: 9 additions & 0 deletions components/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ export const BottomSheet: React.FC<BottomSheetProps> = ({
<div
className="absolute top-2 left-1/2 w-12 h-1 bg-gray-300 transform -translate-x-1/2 cursor-pointer dark:bg-gray-600"
onClick={handleToggleCollapse}
role="button"
tabIndex={0}
aria-label="Toggle bottom sheet"
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
handleToggleCollapse()
}
}}
/>

{isCollapsed ? (
Expand Down
5 changes: 2 additions & 3 deletions components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import {
ChevronLeft,
ChevronRight,
Folder,
Book,
BookOpen
Book
} from 'lucide-react'
import { useAppStore } from '../lib/store'
import { save } from '@tauri-apps/plugin-dialog'
Expand Down Expand Up @@ -175,7 +174,7 @@ export default function Sidebar() {
<div key={project.id} className="flex justify-between items-center px-3 py-1">
<span className="truncate text-caption">{project.name}</span>
<span className="tag-native" style={{ fontSize: '10px', padding: '2px 6px', backgroundColor: 'var(--color-primary-50)', color: 'var(--color-primary-600)' }}>
{project.settings.default_environment}
{project.settings?.defaultEnvironment ?? 'development'}
</span>
</div>
))
Expand Down
1 change: 0 additions & 1 deletion components/UnlockVaultScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useEffect, useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { Key, Shield, Eye, EyeOff, Lock } from 'lucide-react'
import { useAppStore } from '../lib/store'
import KeyringService from '../lib/services/keyringService'

export default function UnlockVaultScreen() {
const [password, setPassword] = useState('')
Expand Down
4 changes: 2 additions & 2 deletions components/modals/AddApiKeyModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,10 @@ export default function AddApiKeyModal() {
</label>
<select
value={formData.environment}
onChange={(e) => setFormData(prev => ({ ...prev, environment: e.target.value as any }))}
onChange={(e) => setFormData(prev => ({ ...prev, environment: e.target.value as 'development' | 'staging' | 'production' }))}
className="input-native"
>
<option value="dev">Development</option>
<option value="development">Development</option>
<option value="staging">Staging</option>
<option value="production">Production</option>
</select>
Expand Down
4 changes: 2 additions & 2 deletions components/modals/EditApiKeyModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ export default function EditApiKeyModal() {
</label>
<select
value={formData.environment}
onChange={(e) => setFormData(prev => ({ ...prev, environment: e.target.value as any }))}
onChange={(e) => setFormData(prev => ({ ...prev, environment: e.target.value as 'development' | 'staging' | 'production' }))}
className="px-3 py-2 w-full text-gray-900 bg-white rounded-lg border border-gray-300 transition-colors dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
<option value="dev">Development</option>
<option value="development">Development</option>
<option value="staging">Staging</option>
<option value="production">Production</option>
</select>
Expand Down
9 changes: 5 additions & 4 deletions extensions/vscode/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "keykeeper-vscode",
"name": "cadcamfun.keykeeper-vscode",
"displayName": "KeyKeeper Enterprise",
"description": "Enterprise-grade Secure API Key Management with .env Drag & Drop and Auto-Activation",
"version": "0.1.0",
"publisher": "nikoemme",
"publisher": "cadcamfun",
"repository": {
"type": "git",
"url": "https://github.com/nikomatt69/keykeeper.git"
Expand All @@ -14,7 +14,7 @@
},
"license": "MIT",
"engines": {
"vscode": "^1.74.0"
"vscode": "^1.85.0"
},
"categories": [
"Other",
Expand Down Expand Up @@ -478,10 +478,11 @@
},
"devDependencies": {
"@types/node": "16.x",
"@types/vscode": "^1.74.0",
"@types/vscode": "^1.85.0",
"@types/ws": "^8.18.1",
"ts-loader": "^9.5.2",
"typescript": "^4.9.4",
"vsce": "^2.15.0",
"webpack": "^5.100.2",
"webpack-cli": "^6.0.1"
},
Expand Down
2 changes: 1 addition & 1 deletion lib/services/apiProviderService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ export class ApiProviderService {

return {
files,
dependencies: [...Array.from(new Set(dependencies[0]))], // Remove duplicates
dependencies: [...new Set(dependencies)],
setupInstructions,
nextSteps
};
Expand Down
34 changes: 23 additions & 11 deletions lib/services/integrationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class IntegrationService {
private backupInProgress = false
private lastBackup: Date | null = null
private initialized = false
private vscodeCheckInterval: ReturnType<typeof setInterval> | null = null
private backupCheckInterval: ReturnType<typeof setInterval> | null = null
private autoLockTimeout: ReturnType<typeof setTimeout> | null = null

// VSCode Integration
async checkVSCodeConnection(): Promise<boolean> {
Expand Down Expand Up @@ -218,7 +221,10 @@ class IntegrationService {

// Security Functions
async triggerAutoLock(timeoutMinutes: number): Promise<void> {
setTimeout(() => {
if (this.autoLockTimeout) {
clearTimeout(this.autoLockTimeout)
}
this.autoLockTimeout = setTimeout(() => {
const { lockVault } = useAppStore.getState()
lockVault()

Expand Down Expand Up @@ -307,31 +313,25 @@ class IntegrationService {

// Initialize service
async initialize(settings: EnterpriseSettings): Promise<void> {
// Prevent duplicate initialization
if (this.initialized) {
return
}

this.initialized = true

// Start VSCode integration if enabled
if (settings.integrations.vscode.enabled) {
await this.enableVSCodeIntegration(true)

// Check connection periodically
setInterval(() => {
this.vscodeCheckInterval = setInterval(() => {
this.checkVSCodeConnection()
}, 30000) // Every 30 seconds
}, 30000)
}

// Schedule auto backup
if (settings.backup.autoBackup) {
setInterval(() => {
this.backupCheckInterval = setInterval(() => {
this.scheduleAutoBackup(settings)
}, 60000) // Check every minute
}, 60000)
}

// Setup auto-lock
if (settings.security.autoLockTimeout > 0) {
this.triggerAutoLock(settings.security.autoLockTimeout)
}
Expand All @@ -351,6 +351,18 @@ class IntegrationService {
lastHeartbeat: null,
connectionCount: 0
}
if (this.vscodeCheckInterval) {
clearInterval(this.vscodeCheckInterval)
this.vscodeCheckInterval = null
}
if (this.backupCheckInterval) {
clearInterval(this.backupCheckInterval)
this.backupCheckInterval = null
}
if (this.autoLockTimeout) {
clearTimeout(this.autoLockTimeout)
this.autoLockTimeout = null
}
}
}

Expand Down
36 changes: 32 additions & 4 deletions lib/services/llmProxyService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@ interface CachedResponse {
}

export class LLMProxyService {
private static instance: LLMProxyService;
private static instance: LLMProxyService | null = null;
private static initPromise: Promise<LLMProxyService> | null = null;
private config: LLMProxyConfig;
private cache = new Map<string, CachedResponse>();
private cacheDuration = 24 * 60 * 60 * 1000; // 24 hours
private cacheDuration = 24 * 60 * 60 * 1000;
private maxCacheSize = 1000;

private constructor(config: Partial<LLMProxyConfig> = {}) {
this.config = {
provider: 'openai', // Default provider
model: 'gpt-4o-mini', // Default model
provider: 'openai',
model: 'gpt-4o-mini',
temperature: 0.2,
maxTokens: 2000,
...config
Expand Down Expand Up @@ -86,6 +88,7 @@ export class LLMProxyService {

try {
const mergedConfig = { ...this.config, ...options };
this.cleanupCache();

console.log('Sending request to LLM proxy:', {
promptLength: prompt.length,
Expand Down Expand Up @@ -162,10 +165,35 @@ export class LLMProxyService {
return response.content;
}

// Clear expired entries from cache
private cleanupCache(): void {
const now = Date.now();
const maxAge = this.cacheDuration;

for (const [key, value] of this.cache.entries()) {
if (now - value.timestamp > maxAge) {
this.cache.delete(key);
}
}

if (this.cache.size > this.maxCacheSize) {
const entries = Array.from(this.cache.entries());
entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
const toRemove = entries.slice(0, Math.floor(this.cache.size * 0.2));
toRemove.forEach(([key]) => this.cache.delete(key));
}
}

// Clear the cache
public clearCache(): void {
this.cache.clear();
}

// Get cache stats
public getCacheStats(): { size: number; maxSize: number } {
this.cleanupCache();
return { size: this.cache.size, maxSize: this.maxCacheSize };
}

// ===============================
// LLM-ENHANCED METHODS
Expand Down
19 changes: 14 additions & 5 deletions lib/services/mlService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,27 @@ interface MLInitRequest extends Record<string, unknown> {
export class MLService {
private static isInitialized = false;
private static initializationPromise: Promise<boolean> | null = null;
private static initPromise: Promise<boolean> | null = null;

/**
* Initialize the ML Engine
*/
static async initialize(config?: MLConfig): Promise<boolean> {
// Avoid multiple initialization attempts
if (this.initializationPromise) {
return this.initializationPromise;
if (this.initPromise) {
return this.initPromise;
}

if (this.isInitialized) {
return true;
}

this.initializationPromise = this._performInitialization(config);
return this.initializationPromise;
this.initPromise = this._performInitialization(config);
try {
const result = await this.initPromise;
return result;
} finally {
this.initPromise = null;
}
}

private static async _performInitialization(config?: MLConfig): Promise<boolean> {
Expand Down
Loading
Loading