Skip to content

[Bug][Critical] Unawaited Async Call in NewFile.tsx Silently Corrupts Invoice Created Timestamp on Every Save #42

@Mandalorian7773

Description

@Mandalorian7773

Ticket Contents (Description):
In Govt-Billing-React/src/components/NewFile/NewFile.tsx (lines 18–20), the application calls props.store._getFile(props.file) without await. Since _getFile returns a Promise backed by Capacitor Preferences, the variable data resolves to a pending Promise object rather than the actual file data. As a result, (data as any).created is always undefined, silently setting the invoice's created timestamp to undefined on every save. For a government billing platform, invoice timestamps are legally significant, corrupted or missing timestamps can invalidate audit trails, break compliance requirements, and cause disputes in procurement workflows. The bug is silent: no error is thrown, no warning is shown to the user, and the data appears saved correctly while the timestamp is actually lost.


Goals & Mid-Point Milestone:

  • Identify all unawaited async calls to Capacitor Preferences / Storage APIs across the React codebase
  • Add await to props.store._getFile(props.file) in NewFile.tsx and ensure the enclosing function is async
  • Audit _getFile and related store methods to confirm they are correctly typed as Promise<T> in TypeScript
  • Enable TypeScript strict mode ("strict": true in tsconfig.json) to surface similar implicit any and missing await issues
  • Add a unit test that saves a new file and asserts the created field is a valid timestamp, not undefined
  • Goals achieved by mid-point: unawaited call fixed, strict mode enabled, test passing

Implementation Details:
Current vulnerable code in Govt-Billing-React/src/components/NewFile/NewFile.tsx:

// BUGGY — _getFile returns a Promise, data is never awaited
const data = props.store._getFile(props.file);
const created = (data as any).created; // always undefined

Proposed fix:

// FIXED — properly await the async store call
const data = await props.store._getFile(props.file);
const created = data.created ?? Date.now(); // fallback if still missing

Also update the enclosing function signature:

// Ensure the parent function is declared async
const handleSave = async () => {
  const data = await props.store._getFile(props.file);
  // ...
};

And enable strict mode in tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true
  }
}

This will surface all other unawaited Promises and implicit any casts across the codebase that may be causing similar silent data corruption.

Tech used: React, TypeScript, Ionic, Capacitor


Product Name: Agentic Invoice Co-Pilot – Web3 Billing for Public Institutions

Organisation Name: NSUT x SEETA x AIC

Domain: Financial Inclusion

Tech Skills Needed: React, TypeScript, Ionic, Mobile

Mentor(s): @seetadev @aspiringsecurity @prithagupta

Category: Bug


Setup/Installation:

cd Govt-Billing-React
npm install
ionic serve
# Create a new invoice file
# Save it
# Inspect the stored record in Capacitor Preferences
# Observe: created field is undefined

Expected Outcome:
Every saved invoice record contains a valid, non-undefined created timestamp reflecting the actual time of creation. The _getFile call is properly awaited so that all fields from Capacitor Preferences are available before the save logic runs. TypeScript strict mode is enabled, preventing similar unawaited async bugs from being introduced in future contributions.


Acceptance Criteria:

  • await is added to all _getFile calls in NewFile.tsx
  • The enclosing function is declared async
  • A saved invoice record always contains a valid created timestamp (not undefined, not null)
  • TypeScript strict mode is enabled in tsconfig.json with no new type errors introduced
  • Unit test confirms created field is a valid number (Unix timestamp) after save
  • No regression in existing save, load, or export functionality

Mockups/Wireframes: N/A, logic fix, no UI changes required

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions