Skip to main content

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 TypeCostDescriptionStatus
signal_view_details5View detailed information about a signal including government contact details✅ Active
signal_pool_request10Save a signal from the pool for review and potential connection✅ Active
connection_request15Request to be connected with a government contact for a specific signal✅ Active
warm_intro_request20Request a warm introduction facilitated by the CivStart team✅ Active

Removed Configurations

Action TypeCostReason for Removal
priority_matching25Did 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:555
  • apps/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 SavedSignal record 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:4480
  • apps/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 ContactRequest or Connection record

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 WarmIntroRequest record
  • 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

  1. All 4 active configurations provide real value to users
  2. Credit costs are logical and increase with value:
    • View details (5) < Pool request (10) < Connection request (15) < Warm intro (20)
  3. Proper metadata tracking for all credit consumption
  4. Consistent implementation pattern across all usage points
  5. Descriptions updated to accurately reflect actual usage

⚠️ Issues Found

  1. 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:4480
      • connection-management.service.ts:285
  2. signal_view_details Charged 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

  1. priority_matching Removed
    • 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:4480
  • apps/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:

  1. Signal Assignment Acceptance

    • When a startup accepts an assigned signal
    • Currently free, could be a credit action
  2. Signal Marker Creation

    • When highlighting/marking specific parts of a signal
    • Currently free
  3. 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

  1. Update descriptions to match actual usage (clarity)
  2. Investigate potential double-charging for connection_request
  3. Verify signal_view_details dual usage is intentional

Next Steps

  1. ✅ Update credit configuration descriptions (this document provides exact text)
  2. 🔍 Investigate connection_request duplicate usage
  3. 🔍 Verify signal_view_details dual implementation
  4. 📝 Update seed script with improved descriptions
  5. 🧪 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