Release 0.1: Complete BinectChrome implementation

Implements all requirements from ProductRequirementsDocument.md:
- PDF detection via Chrome Downloads API
- Secure credential storage with AES-GCM encryption
- Binect API integration for PDF uploads
- Popup UI with Binect branding
- Local transfer tracking (500 entry cap)
- Help page with tracking view and CSV export
- 60-day credential retention with auto-expiry
- Accessibility compliance (WCAG 2.1 AA)

Technical implementation:
- Chrome Extension Manifest V3
- TypeScript with strict mode
- Webpack build system
- Jest test suite (22/22 passing)
- ESLint configured (0 errors)

Build output: 13 KB total (production minified)
Test coverage: crypto, pdf-detector, tracker, binect-api

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-13 00:30:39 +01:00
parent 8f85c51d4e
commit b09290cb83
43 changed files with 12078 additions and 2 deletions

View File

@@ -0,0 +1,101 @@
/**
* Service Worker (Background Script)
* Handles PDF detection and credential expiry checks
*/
import { startPDFDetection, DetectedPDF } from '../utils/pdf-detector';
import { loadCredentials } from '../utils/storage';
// Store last detected PDF in memory (ephemeral)
let lastDetectedPDF: DetectedPDF | null = null;
/**
* Initialize extension on install
*/
chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') {
console.log('BinectChrome installed');
setupCredentialExpiryAlarm();
} else if (details.reason === 'update') {
console.log('BinectChrome updated');
}
});
/**
* Handle extension startup
*/
chrome.runtime.onStartup.addListener(() => {
console.log('BinectChrome started');
setupCredentialExpiryAlarm();
});
/**
* Set up alarm to check credential expiry daily
*/
function setupCredentialExpiryAlarm() {
chrome.alarms.create('checkCredentialExpiry', {
delayInMinutes: 1, // First check in 1 minute
periodInMinutes: 24 * 60 // Then every 24 hours
});
}
/**
* Handle alarm events
*/
chrome.alarms.onAlarm.addListener((alarm) => {
if (alarm.name === 'checkCredentialExpiry') {
checkAndDeleteExpiredCredentials();
}
});
/**
* Check if credentials are expired and delete them
*/
async function checkAndDeleteExpiredCredentials() {
const credentials = await loadCredentials();
// loadCredentials already handles expiry check and deletion
// If credentials are expired, it returns null and deletes them
if (credentials === null) {
console.log('Credentials expired and deleted');
}
}
/**
* Start PDF detection
*/
startPDFDetection((pdf: DetectedPDF) => {
console.log('PDF detected:', pdf.filename);
lastDetectedPDF = pdf;
// Update badge to indicate PDF detected
chrome.action.setBadgeText({ text: '1' });
chrome.action.setBadgeBackgroundColor({ color: '#4A90E2' }); // Binect Blue
});
/**
* Handle messages from popup
*/
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'getLastPDF') {
sendResponse({ pdf: lastDetectedPDF });
return true;
}
if (request.action === 'clearLastPDF') {
lastDetectedPDF = null;
chrome.action.setBadgeText({ text: '' });
sendResponse({ success: true });
return true;
}
if (request.action === 'pdfSent') {
// Clear badge after successful send
chrome.action.setBadgeText({ text: '' });
sendResponse({ success: true });
return true;
}
return false;
});
console.log('BinectChrome service worker loaded');