Implement DDD refactoring phases 1-4 with domain layer and ubiquitous language

Phase 1-3: Domain Layer Foundation
- Add value objects: IdentityId, PermissionId, RelayId, WalletId, Nickname, NostrKeyPair
- Add rich domain entities: Identity, Permission, Relay with behavior
- Add domain events: IdentityCreated, IdentityRenamed, IdentitySelected, etc.
- Add repository interfaces for Identity, Permission, Relay
- Add infrastructure layer with repository implementations
- Add EncryptionService abstraction

Phase 4: Ubiquitous Language Cleanup
- Rename BrowserSyncData → EncryptedVault (encrypted vault storage)
- Rename BrowserSessionData → VaultSession (decrypted session state)
- Rename SignerMetaData → ExtensionSettings (extension configuration)
- Rename Identity_ENCRYPTED → StoredIdentity (storage DTO)
- Rename Identity_DECRYPTED → IdentityData (session DTO)
- Similar renames for Permission, Relay, NwcConnection, CashuMint
- Add backwards compatibility aliases with @deprecated markers

Test Coverage
- Add comprehensive tests for all value objects
- Add tests for domain entities and their behavior
- Add tests for domain events
- Fix PermissionChecker to prioritize kind-specific rules over blanket rules
- Fix pre-existing component test issues (IconButton, Pubkey)

All 113 tests pass. Both Chrome and Firefox builds succeed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
woikos
2025-12-25 05:21:44 +01:00
parent 87d76bb4a8
commit d98a0ef76e
58 changed files with 4927 additions and 277 deletions

View File

@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { SignerMetaData, SignerMetaHandler } from '@common';
import { ExtensionSettings, SignerMetaHandler } from '@common';
export class ChromeMetaHandler extends SignerMetaHandler {
async loadFullData(): Promise<Partial<Record<string, any>>> {
@@ -19,7 +19,7 @@ export class ChromeMetaHandler extends SignerMetaHandler {
return data;
}
async saveFullData(data: SignerMetaData): Promise<void> {
async saveFullData(data: ExtensionSettings): Promise<void> {
await chrome.storage.local.set(data);
}

View File

@@ -1,12 +1,12 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { BrowserSessionData, BrowserSessionHandler } from '@common';
import { VaultSession, BrowserSessionHandler } from '@common';
export class ChromeSessionHandler extends BrowserSessionHandler {
async loadFullData(): Promise<Partial<Record<string, any>>> {
return chrome.storage.session.get(null);
}
async saveFullData(data: BrowserSessionData): Promise<void> {
async saveFullData(data: VaultSession): Promise<void> {
await chrome.storage.session.set(data);
}

View File

@@ -1,12 +1,12 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
BrowserSyncData,
EncryptedVault,
BrowserSyncHandler,
CashuMint_ENCRYPTED,
Identity_ENCRYPTED,
NwcConnection_ENCRYPTED,
Permission_ENCRYPTED,
Relay_ENCRYPTED,
StoredCashuMint,
StoredIdentity,
StoredNwcConnection,
StoredPermission,
StoredRelay,
} from '@common';
/**
@@ -26,20 +26,20 @@ export class ChromeSyncNoHandler extends BrowserSyncHandler {
return data;
}
async saveAndSetFullData(data: BrowserSyncData): Promise<void> {
async saveAndSetFullData(data: EncryptedVault): Promise<void> {
await chrome.storage.local.set(data);
this.setFullData(data);
}
async saveAndSetPartialData_Permissions(data: {
permissions: Permission_ENCRYPTED[];
permissions: StoredPermission[];
}): Promise<void> {
await chrome.storage.local.set(data);
this.setPartialData_Permissions(data);
}
async saveAndSetPartialData_Identities(data: {
identities: Identity_ENCRYPTED[];
identities: StoredIdentity[];
}): Promise<void> {
await chrome.storage.local.set(data);
this.setPartialData_Identities(data);
@@ -53,21 +53,21 @@ export class ChromeSyncNoHandler extends BrowserSyncHandler {
}
async saveAndSetPartialData_Relays(data: {
relays: Relay_ENCRYPTED[];
relays: StoredRelay[];
}): Promise<void> {
await chrome.storage.local.set(data);
this.setPartialData_Relays(data);
}
async saveAndSetPartialData_NwcConnections(data: {
nwcConnections: NwcConnection_ENCRYPTED[];
nwcConnections: StoredNwcConnection[];
}): Promise<void> {
await chrome.storage.local.set(data);
this.setPartialData_NwcConnections(data);
}
async saveAndSetPartialData_CashuMints(data: {
cashuMints: CashuMint_ENCRYPTED[];
cashuMints: StoredCashuMint[];
}): Promise<void> {
await chrome.storage.local.set(data);
this.setPartialData_CashuMints(data);

View File

@@ -1,12 +1,12 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
BrowserSyncData,
CashuMint_ENCRYPTED,
Identity_ENCRYPTED,
NwcConnection_ENCRYPTED,
Permission_ENCRYPTED,
EncryptedVault,
StoredCashuMint,
StoredIdentity,
StoredNwcConnection,
StoredPermission,
BrowserSyncHandler,
Relay_ENCRYPTED,
StoredRelay,
} from '@common';
/**
@@ -18,20 +18,20 @@ export class ChromeSyncYesHandler extends BrowserSyncHandler {
return await chrome.storage.sync.get(null);
}
async saveAndSetFullData(data: BrowserSyncData): Promise<void> {
async saveAndSetFullData(data: EncryptedVault): Promise<void> {
await chrome.storage.sync.set(data);
this.setFullData(data);
}
async saveAndSetPartialData_Permissions(data: {
permissions: Permission_ENCRYPTED[];
permissions: StoredPermission[];
}): Promise<void> {
await chrome.storage.sync.set(data);
this.setPartialData_Permissions(data);
}
async saveAndSetPartialData_Identities(data: {
identities: Identity_ENCRYPTED[];
identities: StoredIdentity[];
}): Promise<void> {
await chrome.storage.sync.set(data);
this.setPartialData_Identities(data);
@@ -45,21 +45,21 @@ export class ChromeSyncYesHandler extends BrowserSyncHandler {
}
async saveAndSetPartialData_Relays(data: {
relays: Relay_ENCRYPTED[];
relays: StoredRelay[];
}): Promise<void> {
await chrome.storage.sync.set(data);
this.setPartialData_Relays(data);
}
async saveAndSetPartialData_NwcConnections(data: {
nwcConnections: NwcConnection_ENCRYPTED[];
nwcConnections: StoredNwcConnection[];
}): Promise<void> {
await chrome.storage.sync.set(data);
this.setPartialData_NwcConnections(data);
}
async saveAndSetPartialData_CashuMints(data: {
cashuMints: CashuMint_ENCRYPTED[];
cashuMints: StoredCashuMint[];
}): Promise<void> {
await chrome.storage.sync.set(data);
this.setPartialData_CashuMints(data);

View File

@@ -27,7 +27,7 @@
>
<span class="text-muted">{{ permission.method }}</span>
@if(typeof permission.kind !== 'undefined') {
<span>(kind {{ permission.kind }})</span>
<span [title]="getKindTooltip(permission.kind!)">(kind {{ permission.kind }})</span>
}
<div class="sam-flex-grow"></div>
<lib-icon-button

View File

@@ -5,6 +5,7 @@ import {
NavComponent,
Permission_DECRYPTED,
StorageService,
getKindName,
} from '@common';
import { ActivatedRoute } from '@angular/router';
@@ -86,4 +87,8 @@ export class PermissionsComponent extends NavComponent implements OnInit {
});
});
}
getKindTooltip(kind: number): string {
return getKindName(kind);
}
}