TaskHub.Shared

Services

The Services layer wraps infrastructure capabilities that aren’t core domain concerns — file storage, geocoding, etc. Each capability is split into an abstraction (the contract your code depends on) and one or more implementations (file system, OpenStreetMap Nominatim, …).

This split lets services swap providers (local disk → S3, Nominatim → Google Maps) without touching domain code.

🎯 Design Goals

  1. Abstraction-first. Domain code talks to IStorageService, never to a specific provider. Tests mock the interface; production wires the concrete.
  2. One implementation per provider. Storage.FileSystem for local; future Storage.S3 for cloud — same abstraction.
  3. Observability built-in. Every operation is traced; storage operations emit hash and size tags.
  4. Result-typed. Operations return Result / ValueResult<T> rather than throwing — failures are first-class values.

📦 Modules

📁 Storage

| Module | Purpose | | :— | :— | | Storage Abstractions | IStorageService, IStorageProvider, IPathGenerator, IHashResolver. | | Storage FileSystem | Local-disk implementation, suitable for single-node deploys and dev. |

📍 GeoCoding

| Module | Purpose | | :— | :— | | GeoCoding Abstractions | IGeoService, PlaceModel, factories. | | GeoCoding Nominatim | OpenStreetMap Nominatim implementation with city query support. |

🧭 Pattern: Abstraction + Provider

   IStorageService               IGeoService
        ▲                              ▲
        │                              │
   ┌────┴────┐                    ┌───┴────┐
   │FileSystem│  (today)          │Nominatim│  (today)
   └─────────┘                    └────────┘
   ┌─────────┐                    ┌────────┐
   │   S3    │  (future)          │ Google │  (future)
   └─────────┘                    └────────┘

Domain handlers depend only on the top interface. Provider choice is a Program.cs decision, not a domain concern.

✅ When to Add a New Service

Add a new service module when you need an infrastructure capability that:

If only one service needs it and there’s only one obvious provider, keep it in that service’s Infrastructure folder.

🔗 Adjacent Modules