feat: implement branded types for type-level security (Phase 1.2)
Add branded types to prevent mixing plaintext, encrypted, and certificate values at compile time. This provides an additional layer of type safety without any runtime cost. ## Changes ### Type System (src/types.ts) - Add PlaintextValue branded type for user input - Add EncryptedValue branded type for encrypted data - Add Base64String branded type for base64-encoded values - Add PEMCertificate branded type for PEM certificates - Add constructor functions for each branded type - Add unwrap() utility for extracting raw strings ### Crypto Module (src/lib/crypto.ts) - Update parsePublicKeyFromCert() to require PEMCertificate - Update encryptValue() to accept PlaintextValue, return Base64String - Update encryptKeyValues() to accept PlaintextValue[], return Base64String[] - Update validateCertificate() to require PEMCertificate ### Controller API (src/lib/controller.ts) - Update fetchPublicCertificate() to return PEMCertificate - Brand certificate at source when fetching from API ### UI Components - EncryptDialog: Brand user input as PlaintextValue before encryption - SealingKeysView: Brand certificates as PEMCertificate when parsing ## Benefits - Zero runtime cost (types erased at compile time) - Prevents passing plaintext where encrypted expected - Prevents passing encrypted where plaintext expected - Self-documenting function signatures - TypeScript enforces correct value handling ## Verification - TypeScript: 0 errors - Linting: 0 errors - Build: Success (340.20 kB, 93.41 kB gzipped) - Build time: 3.99s (improved from 4.64s) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
@@ -27,7 +27,7 @@ import React from 'react';
|
||||
import { fetchPublicCertificate, getPluginConfig } from '../lib/controller';
|
||||
import { encryptKeyValues, parsePublicKeyFromCert } from '../lib/crypto';
|
||||
import { SealedSecret } from '../lib/SealedSecretCRD';
|
||||
import { SealedSecretScope,SecretKeyValue } from '../types';
|
||||
import { PlaintextValue, SealedSecretScope, SecretKeyValue } from '../types';
|
||||
|
||||
interface EncryptDialogProps {
|
||||
open: boolean;
|
||||
@@ -111,7 +111,7 @@ export function EncryptDialog({ open, onClose }: EncryptDialogProps) {
|
||||
// 3. Encrypt all values client-side
|
||||
const encryptResult = encryptKeyValues(
|
||||
keyResult.value,
|
||||
validKeyValues.map(kv => ({ key: kv.key, value: kv.value })),
|
||||
validKeyValues.map(kv => ({ key: kv.key, value: PlaintextValue(kv.value) })),
|
||||
namespace,
|
||||
name,
|
||||
scope
|
||||
|
||||
Reference in New Issue
Block a user