Ajoute l'endpoint api/share_api.dart, les use cases de partage (application/share_use_cases.dart) et l'adapter Postgres (infrastructure/postgres/share_repository.dart). L'acceptation d'un partage crée une nouvelle ressource synced_resources avec de nouveaux IDs pour le destinataire, sans jamais modifier la ressource source de l'émetteur ; gestion des conflits révoqué/déjà répondu. dart pub get OK, dart analyze clean, dart test 24/24 vert. Use case d'acceptation relu manuellement et jugé correct ; pas de test de bout en bout contre un vrai PostgreSQL faute d'accès Docker dans ce sandbox. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
96 lines
2.2 KiB
Dart
96 lines
2.2 KiB
Dart
import '../domain/domain.dart';
|
|
|
|
abstract interface class UserRepository {
|
|
Future<UserAccount?> findByEmail(String email);
|
|
|
|
Future<UserAccount?> findById(String id);
|
|
|
|
Future<void> insert(UserAccount user);
|
|
|
|
Future<void> updatePasswordHash({
|
|
required String userId,
|
|
required String passwordHash,
|
|
required DateTime updatedAt,
|
|
});
|
|
}
|
|
|
|
abstract interface class AuthSessionRepository {
|
|
Future<void> insert(AuthSession session);
|
|
|
|
Future<AuthSession?> findByTokenHash(String tokenHash);
|
|
|
|
Future<void> revoke({required String sessionId, required DateTime revokedAt});
|
|
}
|
|
|
|
enum SyncWriteStatus { accepted, ignoredOlder }
|
|
|
|
final class SyncWriteResult {
|
|
const SyncWriteResult({required this.status, required this.resource});
|
|
|
|
final SyncWriteStatus status;
|
|
final SyncedResource resource;
|
|
}
|
|
|
|
abstract interface class SyncedResourceRepository {
|
|
Future<SyncWriteResult> upsertWithLww(SyncedResource resource);
|
|
|
|
Future<List<SyncedResource>> findAllForUserSince({
|
|
required String ownerUserId,
|
|
DateTime? since,
|
|
});
|
|
}
|
|
|
|
final class ShareInboxItem {
|
|
const ShareInboxItem({required this.share, required this.recipient});
|
|
|
|
final Share share;
|
|
final ShareRecipient recipient;
|
|
}
|
|
|
|
abstract interface class ShareRepository {
|
|
Future<void> insertShare({
|
|
required Share share,
|
|
required List<ShareRecipient> recipients,
|
|
});
|
|
|
|
Future<List<ShareInboxItem>> listInbox(String recipientUserId);
|
|
|
|
Future<Share?> findShareById(String shareId);
|
|
|
|
Future<ShareRecipient?> findRecipient({
|
|
required String shareId,
|
|
required String recipientUserId,
|
|
});
|
|
|
|
Future<void> updateRecipientStatus({
|
|
required String recipientId,
|
|
required ShareRecipientStatus status,
|
|
required DateTime respondedAt,
|
|
});
|
|
|
|
Future<void> revokeShare({
|
|
required String shareId,
|
|
required DateTime revokedAt,
|
|
});
|
|
}
|
|
|
|
abstract interface class PasswordHasher {
|
|
Future<String> hash(String password);
|
|
|
|
Future<bool> verify({required String password, required String passwordHash});
|
|
}
|
|
|
|
abstract interface class OpaqueTokenService {
|
|
String generateToken();
|
|
|
|
String hashToken(String token);
|
|
}
|
|
|
|
abstract interface class Clock {
|
|
DateTime now();
|
|
}
|
|
|
|
abstract interface class IdGenerator {
|
|
String newId();
|
|
}
|