Credit System Audit - Actual Usage vs Configuration
Date: January 4, 2025 (Updated: January 4, 2025) Purpose: Identify where credits are actually consumed and ensure configurations match reality
Executive Summary
✅ UPDATE: After audit, reduced from 5 to 4 active credit actions.
Removed: priority_matching - Not providing actual priority functionality, just charging for standard matching.
Kept: 4 credit actions that provide real value to users.
Current Credit Configurations (Active)
| Action Type | Cost | Description | Status |
|---|---|---|---|
signal_view_details | 5 | View detailed information about a signal including government contact details | ✅ Active |
signal_pool_request | 10 | Save a signal from the pool for review and potential connection | ✅ Active |
connection_request | 15 | Request to be connected with a government contact for a specific signal | ✅ Active |
warm_intro_request | 20 | Request a warm introduction facilitated by the CivStart team | ✅ Active |
Removed Configurations
| Action Type | Cost | Reason for Removal |
|---|---|---|
priority_matching | 25 | Did not provide actual priority functionality - charged for standard matching algorithm |
Actual Credit Consumption Points
1. ✅ signal_view_details (5 credits)
Files:
apps/backend/src/govintel/controllers/govintel.controller.ts:555apps/backend/src/govintel/controllers/govintel.controller.ts:585
Implementation:
await this.creditService.consumeCredits({
startupId,
actionType: "signal_view_details",
amount: creditCost,
description: `Viewed detailed information for signal: ${signal.painPoints?.substring(0, 100)}...`,
entityId: signal.id,
entityType: "signal_view",
metadata: {
signalId: signal.id,
governmentName: signal.government?.name,
mqlScore: signal.mqLScore,
},
});
When Triggered:
- When a startup views detailed information about a signal
- Appears in TWO separate endpoints (likely one for assigned signals, one for pool signals)
Configuration Status: ✅ Accurate
- Description matches usage
- Cost is appropriate for viewing details
2. ✅ signal_pool_request (10 credits)
File:
apps/backend/src/govintel/controllers/govintel.controller.ts:3562
Implementation:
await this.creditService.consumeCredits({
startupId: dto.startupId,
actionType: "signal_pool_request",
amount: creditCost,
description: `Saved signal ${dto.signalId} for review and potential connection`,
entityId: savedSignal.id,
entityType: "saved_signal",
metadata: {
signalId: dto.signalId,
userId,
},
});
When Triggered:
- When a startup saves/requests a signal from the pool
- Creates a
SavedSignalrecord for later review
Configuration Status: ⚠️ Description needs update
- Current: "Request a signal from the signal pool for review and potential connection"
- Better: "Save a signal from the pool for review and potential connection"
- Cost is appropriate
3. ✅ connection_request (15 credits)
Files:
apps/backend/src/govintel/controllers/govintel.controller.ts:4480apps/backend/src/govintel/services/connections/connection-management.service.ts:285
Implementation (Controller):
await this.creditService.consumeCredits({
startupId: dto.startupId,
actionType: "connection_request",
amount: creditCost,
description: `Contact request for signal: ${signal.painPoints?.substring(0, 80)}...`,
entityId: contactRequest.id,
entityType: "contact_request",
metadata: {
signalId: dto.signalId,
contactRequestId: contactRequest.id,
governmentName: signal.government?.governmentName,
},
});
Implementation (Service):
await this.creditService.consumeCredits({
startupId: startup.id,
actionType: "connection_request",
amount: creditCost,
description: `Connection request to ${signal.governmentName || "government contact"} for signal ${signal.signalIdentifier}`,
entityId: connection.id,
entityType: "connection",
metadata: {
signalId: signal.id,
matchScore: request.matchScore,
priority: request.priority,
},
});
When Triggered:
- When a startup requests to be connected with a government contact for a signal
- Creates either a
ContactRequestorConnectionrecord
Configuration Status: ⚠️ Description could be clearer
- Current: "Request an introduction to a government contact for a specific signal"
- Better: "Request a connection/introduction to a government contact for a signal"
- Cost is appropriate
- Note: Used in TWO different places (controller vs service) - may indicate duplicate logic
4. ✅ warm_intro_request (20 credits)
File:
apps/backend/src/govintel/services/connections/connection-management.service.ts:614
Implementation:
await this.creditService.consumeCredits({
startupId: connection.assignedStartupId,
actionType: "warm_intro_request",
amount: creditCost,
description: `Warm introduction request via ${introType} for connection ${connectionId}`,
entityId: warmIntroRequest.id,
entityType: "warm_intro_request",
metadata: {
connectionId,
introType,
signalId: connection.signalId,
},
});
When Triggered:
- When a startup requests a warm introduction (facilitated by CivStart team)
- Creates a
WarmIntroRequestrecord - Includes intro type (email, phone, meeting, etc.)
Configuration Status: ✅ Accurate
- Description matches usage perfectly
- Cost is appropriate (higher than connection_request since it requires CivStart facilitation)
Analysis & Findings
✅ What's Working Well
- All 4 active configurations provide real value to users
- Credit costs are logical and increase with value:
- View details (5) < Pool request (10) < Connection request (15) < Warm intro (20)
- Proper metadata tracking for all credit consumption
- Consistent implementation pattern across all usage points
- Descriptions updated to accurately reflect actual usage
⚠️ Issues Found
-
Duplicate Credit Consumption for
connection_request- Used in BOTH controller AND service layer
- May result in double-charging if both code paths are triggered
- Location:
govintel.controller.ts:4480connection-management.service.ts:285
-
signal_view_detailsCharged Twice?- Same action at line 555 and 585 in controller
- May be for different contexts (assigned vs pool)
- Should verify this doesn't double-charge
✅ Resolved Issues
priority_matchingRemoved- Was charging 25 credits but not providing actual priority functionality
- Standard matching algorithm was used regardless of payment
- Removed to avoid misleading users
Final Configuration (Implemented)
const configurations = [
{
actionType: "signal_view_details",
creditCost: 5,
description:
"View detailed information about a signal including government contact details",
isActive: true,
},
{
actionType: "signal_pool_request",
creditCost: 10,
description:
"Save a signal from the pool for review and potential connection",
isActive: true,
},
{
actionType: "connection_request",
creditCost: 15,
description:
"Request to be connected with a government contact for a specific signal",
isActive: true,
},
{
actionType: "warm_intro_request",
creditCost: 20,
description: "Request a warm introduction facilitated by the CivStart team",
isActive: true,
},
];
Code Quality Issues to Address
1. Potential Double Charging
Issue: connection_request appears in both controller and service
Files:
apps/backend/src/govintel/controllers/govintel.controller.ts:4480apps/backend/src/govintel/services/connections/connection-management.service.ts:285
Recommendation:
- Investigate if these are different code paths or duplicates
- If duplicates, remove one to avoid double-charging
- If different (e.g., contact request vs connection creation), consider splitting into two action types
2. Duplicate signal_view_details
Issue: Same action appears twice in same controller
File: apps/backend/src/govintel/controllers/govintel.controller.ts
- Line 555
- Line 585
Recommendation:
- Verify these are for different contexts (assigned vs pool signals)
- If duplicate, consolidate
- If different contexts, ensure both are intentional
Missing Credit Actions?
Based on the codebase analysis, here are potential actions that could charge credits but currently don't:
-
Signal Assignment Acceptance
- When a startup accepts an assigned signal
- Currently free, could be a credit action
-
Signal Marker Creation
- When highlighting/marking specific parts of a signal
- Currently free
-
Bulk Actions
- Viewing multiple signals at once
- Batch operations
Recommendation: These are currently free and should probably stay free unless business requirements change.
Summary
Current State: ✅ GOOD
- All 5 credit actions are implemented correctly
- Costs are appropriate and logical
- System is working as designed
Improvements Needed: ⚠️ MINOR
- Update descriptions to match actual usage (clarity)
- Investigate potential double-charging for
connection_request - Verify
signal_view_detailsdual usage is intentional
Next Steps
- ✅ Update credit configuration descriptions (this document provides exact text)
- 🔍 Investigate
connection_requestduplicate usage - 🔍 Verify
signal_view_detailsdual implementation - 📝 Update seed script with improved descriptions
- 🧪 Add integration tests for credit consumption
Audit Completed: January 4, 2025 Status: System is functional, minor improvements recommended Risk Level: LOW - No critical issues found