Skip to content

feat: implement protocols section and fix backend DI issue#150

Open
Rajkoli145 wants to merge 6 commits intoInferara:mainfrom
Rajkoli145:feat/protocols-section
Open

feat: implement protocols section and fix backend DI issue#150
Rajkoli145 wants to merge 6 commits intoInferara:mainfrom
Rajkoli145:feat/protocols-section

Conversation

@Rajkoli145
Copy link
Contributor

Description

This PR adds the new “Protocols” section as requested.
It introduces a /protocols page to make browsing audited protocols and viewing their security metrics easier and more centralized.

Changes Made

  1. Protocols Page
    • Created a new /protocols route.
    • Implemented a responsive grid layout.
    • Displayed protocol cards with:
    • Protocol name & logo
    • Company name
    • Total audit reports
    • Vulnerabilities
    • Fixed issues
    • Fix rate %

  2. Search & Filtering
    • Added client-side search.
    • Supports filtering by:
    • Name
    • Company
    • Auditor
    • Description

  3. Navigation Integration
    • Added “Protocols” to the main navigation.
    • Registered routing in MainWindow.tsx.

Local Testing

To validate the feature properly, I temporarily seeded sample protocol, report, and vulnerability data to verify:
• Correct metric aggregation
• Working multi-field search
• Proper UI rendering with real data

The seed logic has been removed from this PR.

Verification
• Confirmed backend runs locally (Port 7878).
• Verified search filtering works as expected.
• Tested responsive layout across screen sizes

Demo Video:

Protocol-demo.mov

close #149

@SurfingBowser
Copy link
Collaborator

hello @Rajkoli145 Thank you for the submission and small demo video that you included.

Could you add some additional search filters similar to the reports page?

For example having the protocols search by default would be helpful, it let's users type the protocol themselves or choose from the existing list.

image image

I would recommend the default search box using the "protocol" search filter same as the Vulnerabilities page If you can't see the filter by default, press the collapsing pyramid icon

Also having the company & auditor search drop down list available would be useful.

Thanks again and let me know if you have any questions or comments

@Rajkoli145
Copy link
Contributor Author

Thanks @SurfingBowser for the feedback!
I’ll update the Protocols page to include the Protocol, Company, and Auditor dropdown filters to match the Reports/Vulnerabilities UX pattern.
I’ll align the default search behavior as suggested and push an update shortly.

@Rajkoli145
Copy link
Contributor Author

Hii @SurfingBowser Implemented advanced search filters for the Protocols page

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a new Protocols page to improve navigation and discoverability of audited protocols. The feature addresses issue #149 by adding a centralized view of all protocols with their security metrics. Additionally, it includes a critical backend dependency injection fix that resolves a service lifetime conflict that would have prevented the application from starting.

Changes:

  • Added a new /protocols route with a responsive grid layout displaying protocol cards with audit metrics (reports, vulnerabilities, fixed issues, fix rate)
  • Implemented client-side search and multi-select filtering by protocol name, company, auditor, and description
  • Changed processor services from Scoped to Singleton lifetime in DI container to fix compatibility with background service (processors use IDbContextFactory pattern making them safe as singletons)

Reviewed changes

Copilot reviewed 6 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
UI/src/features/pages/regular/protocols/protocols.tsx Main protocols page component with card-based grid layout, search, and filtering UI
UI/src/features/pages/regular/protocols/hooks/useProtocols.hook.ts Custom hook managing protocols data fetching, filtering logic, and metrics calculation
UI/src/features/pages/regular/protocols/hooks/index.ts Barrel export file for hooks
UI/src/features/pages/regular/main-window/main-window.tsx Adds "Protocols" navigation item and route registration
UI/public/env.js Formatting cleanup (trailing whitespace)
UI/package-lock.json Peer dependency metadata updates for proper package resolution
Backend/SorobanSecurityPortalApi/Startup.cs Changes processor registration from AddScoped to AddSingletons to fix DI lifetime mismatch
Backend/SorobanSecurityPortalApi/Services/ProcessingServices/BackgroundWorkingHostedService.cs Refactors StartAsync to use fire-and-forget pattern with improved error handling
Files not reviewed (1)
  • UI/package-lock.json: Language not supported
Comments suppressed due to low confidence (4)

UI/src/features/pages/regular/protocols/protocols.tsx:298

  • The IconButton lacks an accessible label (aria-label or title attribute). Screen reader users won't know what this button does. Add an aria-label such as "View protocol details in fullscreen" or a Tooltip component to provide context for assistive technologies and improve accessibility.
                                            <IconButton
                                                sx={{
                                                    borderRadius: '10px',
                                                    border: '1px solid',
                                                    borderColor: 'divider'
                                                }}
                                                onClick={() => navigate(`/protocol/${protocol.id}`)}
                                            >
                                                <FullscreenIcon />
                                            </IconButton>

UI/src/features/pages/regular/protocols/hooks/useProtocols.hook.ts:97

  • The getProtocolMetrics function is called for each protocol during rendering, and each call filters through all reports and vulnerabilities arrays. With many protocols, reports, and vulnerabilities, this could cause performance issues. Consider memoizing the results using useMemo to compute metrics once when the underlying data changes, or pre-compute all metrics in the hook and return a Map of protocol IDs to metrics. This would reduce the time complexity from O(n*m) where n is protocols and m is reports+vulnerabilities, to O(m) for pre-computation.
    const getProtocolMetrics = (protocolId: number) => {
        const protocolReports = reports.filter(r => r.protocolId === protocolId);
        const protocolVulnerabilities = vulnerabilities.filter(v => v.protocolId === protocolId);

        const totalVulnerabilities = protocolVulnerabilities.length;
        const fixedVulnerabilities = protocolVulnerabilities.filter(v => v.category === VulnerabilityCategory.Valid).length;
        const fixRate = totalVulnerabilities > 0 ? Math.round((fixedVulnerabilities / totalVulnerabilities) * 100) : 0;

        return {
            reportsCount: protocolReports.length,
            vulnerabilitiesCount: totalVulnerabilities,
            fixedCount: fixedVulnerabilities,
            fixRate,
            companyName: protocolReports.length > 0 ? protocolReports[0].companyName : 'N/A',
            auditors: Array.from(new Set(protocolReports.map(r => r.auditorName))).filter(Boolean) as string[]
        };
    };

UI/src/features/pages/regular/protocols/hooks/useProtocols.hook.ts:86

  • The logic for calculating fixed vulnerabilities only counts vulnerabilities with category VulnerabilityCategory.Valid (0), which represents "Valid (Fixed)". This excludes partially fixed vulnerabilities (VulnerabilityCategory.ValidPartiallyFixed). Consider whether the fix rate calculation should include all types of fixes or only fully fixed vulnerabilities. The codebase shows inconsistent patterns - company-details.hook.ts uses the same approach (only counting Valid), while protocol-details.hook.ts uses status field instead. For consistency and accuracy, consider whether partially fixed vulnerabilities should contribute to the fix count or be tracked separately.
        const fixedVulnerabilities = protocolVulnerabilities.filter(v => v.category === VulnerabilityCategory.Valid).length;

Backend/SorobanSecurityPortalApi/Services/ProcessingServices/BackgroundWorkingHostedService.cs:52

  • The StartAsync method has been changed from async Task to Task with a fire-and-forget pattern using Task.Run without awaiting. While this prevents blocking during service startup, it creates an unobserved task that could silently fail. The cancellation token is passed to Task.Run, but if an exception occurs in the background loop before the try-catch blocks, it won't be logged. Consider adding a top-level try-catch around the Task.Run lambda or using a continuation to handle unobserved exceptions.
            _ = Task.Run(async () =>
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        await Task.Run(AutoCompactLargeObjectHeap, cancellationToken);
                        await DoReportsFix();
                        await DoReportsEmbedding();
                        await DoVulnerabilitiesEmbedding();
                        await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
                    }
                    catch (OperationCanceledException)
                    {
                        break;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Error in background worker: {ex.Message}");
                        await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
                    }
                }
            }, cancellationToken);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@0xGeorgii 0xGeorgii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rajkoli145 thank you for contributing, please address comments

services.ForInterfacesMatching("^I.*Processor$")
.OfAssemblies(Assembly.GetExecutingAssembly())
.AddScoped();
.AddSingletons();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert this

public Task StartAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
_ = Task.Run(async () =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_ = Task.Run(...) -- the Task is discarded. If an unhandled exception escapes, it's silently lost. Use BackgroundService instead it's the standard .NET pattern for this exact scenario. Inherit from BackgroundService and override ExecuteAsync. Use ILogger<T> with the full exception, not just ex.Message.

const fetchData = async () => {
setLoading(true);
try {
const [protocolsData, reportsData, vulnerabilitiesData, companiesData, auditorsData] = await Promise.all([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is O(P * (R + V)) on every render. As the database grows, this will be extremely slow. Add a backend endpoint (e.g., /api/v1/protocols/with-metrics) that returns pre-computed metrics, consistent with
existing statistics endpoints for other entities.

setCompaniesList(companiesData);
setAuditorsList(auditorsData);
} catch (error) {
console.error('Failed to fetch protocols data:', error);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hook catches errors with console.error but has no error state. If API calls fail, users see "No protocols found" instead of an error message. Other pages expose an error field -- this should too.

}
}}>
<Box sx={{ position: 'relative', pt: '56.25%', bgcolor: themeMode === 'light' ? '#fff' : '#222', borderRadius: '20px 20px 0 0', overflow: 'hidden' }}>
<CardMedia
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cards use raw CardMedia with no loading state, no error fallback, and no 404 handling. Follow the image loading UX pattern from reports.tsx.

}, [searchText, protocolsList, reports, selectedProtocols, selectedCompanies, selectedAuditors]);

// Aggregate metrics for each protocol
const getProtocolMetrics = (protocolId: number) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is recreated on every render and called for each protocol card. Pre-compute a Map<number, Metrics> with useMemo instead.


{showFilters && (
<Box sx={{ mb: 4, display: 'flex', flexWrap: 'wrap', gap: 2, alignItems: 'center', p: 2, borderRadius: '12px', bgcolor: themeMode === 'light' ? '#f5f5f5' : '#222', border: '1px solid', borderColor: 'divider' }}>
<Autocomplete
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MUI will emit console warnings about object comparison. Add: isOptionEqualToValue={(option, value) => option.id === value.id}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both "View Details" and the FullscreenIcon button navigate to the same URL. Remove one.

- Refactored background worker to standard .NET BackgroundService pattern
- Corrected dependency injection for processors to AddScoped
- Optimized Protocols page performance by moving metrics calculation to the backend
- Polished Frontend UX: fixed Autocomplete warnings, added image loading states, and simplified navigation
- Added robust error handling and API status feedback to useProtocols hook
@Rajkoli145
Copy link
Contributor Author

Hi @0xGeorgii , all requested changes are implemented, including moving metrics calculation to the backend. Ready for a review

@Rajkoli145
Copy link
Contributor Author

hii @0xGeorgii Could you please review it when you get a chance? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a "Protocol" section on navigation bar

4 participants