Scope
The two things the Admin module itself owns: a cross-source webhook delivery log and the dashboard summary endpoint.
Webhook delivery log
All three webhook sources (GitHub practice repo, GitHub org, Stripe) already persist delivery/event ids for idempotency. Extend that seam into a queryable log: source, delivery id, event type, received-at, outcome (processed / duplicate / invalid-signature / handler-failed + error summary).
| Method |
Path |
Notes |
| GET |
/admin/webhooks/deliveries?source=&outcome= |
last N (paginated, newest first) — invaluable for debugging redeliveries |
Implementation: either widen each module's delivery table and expose via a small contract per module, or a shared webhook_deliveries table in the Admin schema written through a SharedKernel interface — pick whichever keeps module boundaries clean and document the choice in the PR.
Dashboard summary
| Method |
Path |
Notes |
| GET |
/admin/summary |
counts for the sidebar/landing: pending members, active members, submitted posts (badge count), active mentorships, upcoming sessions, active sponsors, MRR |
Each count sourced through the owning module's public contract — the Admin module aggregates, never queries foreign schemas directly.
Dependencies
Blocked by #1. Counts degrade gracefully (0) for modules not yet built — do not block on Phases 4–7; wire each count as its module lands.
Acceptance criteria
Conventions (project-wide, non-negotiable)
- .NET 9, records for immutable shapes, file-scoped namespaces, primary constructors where they read well. Minimal-API endpoints grouped per module via
IEndpointModule.MapEndpoints.
Result<T> (SharedKernel) instead of exception-driven control flow. Endpoint results map failures to ProblemDetails with the stable error codes listed above — the frontend keys off them.
- Module owns its EF Core
DbContext mapped to its own Postgres schema. Modules never reference each other's internals — cross-module needs go through a public contract interface or an in-process domain event (IEventPublisher).
- All external calls (GitHub, Stripe, Brevo, Cloudinary, Meilisearch) behind interfaces owned by the consuming module.
- Every list endpoint paginated (offset is fine). xUnit tests in
tests/CommunityPro.Tests/<Module>/ following the existing harness patterns (see Members/MembersTestHarness.cs).
Scope
The two things the Admin module itself owns: a cross-source webhook delivery log and the dashboard summary endpoint.
Webhook delivery log
All three webhook sources (GitHub practice repo, GitHub org, Stripe) already persist delivery/event ids for idempotency. Extend that seam into a queryable log: source, delivery id, event type, received-at, outcome (processed / duplicate / invalid-signature / handler-failed + error summary).
/admin/webhooks/deliveries?source=&outcome=Implementation: either widen each module's delivery table and expose via a small contract per module, or a shared
webhook_deliveriestable in the Admin schema written through a SharedKernel interface — pick whichever keeps module boundaries clean and document the choice in the PR.Dashboard summary
/admin/summaryEach count sourced through the owning module's public contract — the Admin module aggregates, never queries foreign schemas directly.
Dependencies
Blocked by #1. Counts degrade gracefully (0) for modules not yet built — do not block on Phases 4–7; wire each count as its module lands.
Acceptance criteria
Conventions (project-wide, non-negotiable)
IEndpointModule.MapEndpoints.Result<T>(SharedKernel) instead of exception-driven control flow. Endpoint results map failures to ProblemDetails with the stable error codes listed above — the frontend keys off them.DbContextmapped to its own Postgres schema. Modules never reference each other's internals — cross-module needs go through a public contract interface or an in-process domain event (IEventPublisher).tests/CommunityPro.Tests/<Module>/following the existing harness patterns (seeMembers/MembersTestHarness.cs).