Scouttlo
All ideas/contact management/A SaaS platform providing a multi-tenant contact management module with persistence, admin endpoints, and built-in GDPR compliance.
GitHubB2BCRMcontact management

A SaaS platform providing a multi-tenant contact management module with persistence, admin endpoints, and built-in GDPR compliance.

Scouted 11 hours ago

7.3/ 10
Overall score

Turn this signal into an edge

We help you build it, validate it, and get there first.

From detected pain to an actionable plan: who pays, which MVP to launch first, how to validate it with real users, and what to measure before spending months.

Expanded analysis

See why this idea is worth it

Unlock the full write-up: what the opportunity really means, what problem exists today, how this idea attacks the pain, and the key concepts you need to know to build it.

We'll only use your email to send you the digest. Unsubscribe any time.

Score breakdown

Urgency8.0
Market size7.0
Feasibility8.0
Competition6.0
The pain

Unified and secure management of contacts across multi-tenant and host-scoped customers in SaaS applications is complex and requires privacy compliance.

Who'd pay

SaaS companies managing multiple clients or tenants needing contact handling with privacy and centralized administration.

Signal that triggered it

"Ship the new `Granit.Contacts` module: `Contact` aggregate + persistence + admin endpoints + GDPR handlers."

Original post

[FEATURE] Granit.Contacts module — domain, persistence, endpoints, privacy

Published: 11 hours ago

Repository: granit-fx/granit-dotnet Author: jfmeyers ## Parent epic #1220 ## Goal Ship the new `Granit.Contacts` module: `Contact` aggregate + persistence + admin endpoints + GDPR handlers. **No migration of downstream modules in this feature** — this lands the module in isolation so it can be reviewed standalone and consumed by Features 2–5 in subsequent PRs. ## Dual-use design (see Epic for context) The `Contact` aggregate is `IMultiTenant`: - `TenantId == null` ⇒ **host-scoped customer** (the SaaS host's B2B customers — i.e. its tenants viewed as billable entities) - `TenantId == <tenant>` ⇒ **tenant-scoped customer** (an e-commerce app running on a tenant stores its own end-customers here) Both kinds share the same table, same behavior, same admin endpoints — the existing `IMultiTenant` query filter handles isolation. Tenant admins see only their own customers; host admins (no tenant context) see host-scoped customers and can opt-in to cross-tenant browsing via `IDataFilter.Disable<IMultiTenant>()`. ## Module split (Granit convention) - `Granit.Contacts` — abstractions: `Contact` aggregate (with `IMultiTenant`), `ContactExternalMapping`, `BillingAddress` (moved here from Invoicing), `ContactStatus`, `ContactId` value object, reader/writer interfaces, domain + integration events, `GranitCustomersModule` - `Granit.Contacts.EntityFrameworkCore` — `ContactsDbContext`, `EfContactStore`, `EfContactQueryableSource`, entity configurations - `Granit.Contacts.Endpoints` — admin CRUD + external mapping management endpoints (visible at both host and tenant scope; permissions split `Contacts.Manage` per `MultiTenancySides`) - `Granit.Contacts.Privacy` — `IPersonalDataExportHandler` + `IPersonalDataDeletionHandler` for the customer's personal-data fields (email, billing address). DPO-driven. - `Granit.Contacts.Tests` (+ `.Tests.Integration` if needed) ## User stories - #1226 - Design Contact aggregate, value objects, and events - #1227 - EF Core persistence — ContactsDbContext, EfContactStore, configurations - #1228 - Admin endpoints — CRUD + external mapping management - #1229 - Privacy handlers — IPersonalDataExportHandler + IPersonalDataDeletionHandler - #1230 - Validate dual-use semantics — host-scope and tenant-scope coexistence - #1231 - Default customer resolver — bridge from tenantId to host-scoped customer ## Acceptance criteria - All four packages compile and reference each other per `[DependsOn]` convention - `dotnet test` green for the new test projects, coverage ≥ 80% on the module - Architecture tests pass (`Granit.ArchitectureTests`); pairing rule satisfied (`CustomerQueryDefinition` + `CustomerExportDefinition`) - `dotnet format --verify-no-changes` clean - New test projects added to `.github/test-shards.json` (likely the `business` shard) - Endpoints exposed at both `/contacts` (tenant scope) and `/admin/contacts` (host scope) per Granit's MultiTenancySides convention

Your daily digest

Liked this one? Get 5 like it every morning.

SaaS opportunities scored by AI on urgency, market size, feasibility and competition. Curated from Reddit, HackerNews and more.

Free. No spam. Unsubscribe any time.