Skip to content

feat: implement typed frappe api client and secure auth poc (#18)#21

Open
rohansaini-02 wants to merge 1 commit into
theapprenticeproject:mainfrom
rohansaini-02:feature/frappe-api-client
Open

feat: implement typed frappe api client and secure auth poc (#18)#21
rohansaini-02 wants to merge 1 commit into
theapprenticeproject:mainfrom
rohansaini-02:feature/frappe-api-client

Conversation

@rohansaini-02
Copy link
Copy Markdown

Summary

Implementation of a standalone Typed Frappe API Client and Secure Authentication Layer (Proof of Concept). This module provides a centralized, secure, and type-safe mechanism for the React Native app to communicate with the Frappe LMS backend, setting the foundation for all future network interactions.

Related Issue

Closes #18

Problem Statement

TAP Buddy requires a robust way to interact with the Frappe LMS backend. A naive approach of making raw HTTP calls throughout the app leads to duplicated authentication logic, inconsistent error handling, and fragile data structures. We need a centralized client that handles api_key:api_secret injection, manages token expiration, and provides strict TypeScript models for our core entities (Users, Courses, Lessons).

Changes Made

  • Isolated Module Creation: Developed poc-frappe-api as a standalone TypeScript package to ensure core networking logic is independently reviewable and testable.
  • FrappeClient Implementation: Built a robust Axios wrapper with built-in interceptors.
  • Secure Auth Abstraction: Created an AuthService interface to manage credentials (designed to be backed by react-native-keychain in production).
  • Automated Header Injection: Implemented a request interceptor to automatically attach the Authorization header to all outgoing requests.
  • Centralized Error Handling: Added a response interceptor to catch 401 Unauthorized errors globally and clear compromised credentials.
  • Data Modeling: Defined comprehensive TypeScript interfaces (LMSCourse, LMSLesson, UserProfile, etc.) to enforce data consistency.
  • Automated Validation: Integrated a Jest test suite to verify interceptor logic.

Technical Decisions

  • Axios Interceptors: Chose interceptors over manual header injection per-request to guarantee that authentication is never accidentally omitted.
  • Abstract Auth Service: By using an interface (IAuthService), the client remains decoupled from React Native specifics, allowing this PoC to be tested in a pure Node environment while being 100% production-ready for the final app.
  • Modular Isolation: Maintained the practice of building in a sub-directory to avoid root-level pollution during the scaffolding phase.

Architectural Rationale: Why #18 precedes #14 (DIKSHA)

I deliberately prioritized this API Client (#18) before tackling the DIKSHA Content Interoperability (#14) for the following reasons:

  1. Downstream Dependency: Tracking DIKSHA progress requires communicating with Frappe. Without this typed API client, we have no secure or standardized way to send that progress data back to the LMS.
  2. Security Baseline: We must establish the Secure Auth Layer before implementing content features to ensure student credentials and data are protected from day one.
  3. Data Contract: This PR establishes the TypeScript interfaces (the "Data Contract") that the DIKSHA module will eventually rely upon, preventing future refactoring.

Testing Performed

  • Interceptor Logic: Verified that the request interceptor correctly formats and attaches the token.
  • Error Recovery: Validated that 401/403 responses trigger the clearCredentials workflow.
  • Type Checking: Ensured all exported models strictly adhere to the expected Frappe DocType schemas.

Results

A secure, typed, and reusable API layer that serves as the foundation for all future LMS-related network calls. This effectively de-risks the communication layer of the application.

Checklist

  • Code follows project conventions
  • Tests pass
  • Documentation updated
  • Changes are scoped to one problem

Architecture Diagram

sequenceDiagram
    participant App as React Native App
    participant Client as FrappeClient
    participant Auth as AuthService (Keychain)
    participant API as Frappe LMS Backend

    %% Request Flow
    App->>Client: getCourses() / getProfile()
    Note over Client: Request Interceptor triggers
    
    Client->>Auth: getCredentials()
    Auth-->>Client: Returns { apiKey, apiSecret }
    
    Note over Client: Injects "Authorization: token key:secret"
    Client->>API: HTTP Request

    %% Success Flow
    alt 200 OK
        API-->>Client: Response Data
        Client-->>App: Strongly Typed Object (LMSCourse[])
    
    %% Error Flow
    else 401 / 403 Unauthorized
        API-->>Client: 401 Unauthorized
        Note over Client: Response Interceptor triggers
        Client->>Auth: clearCredentials()
        Client-->>App: Throws Error
    end
Loading

@rohansaini-02 rohansaini-02 force-pushed the feature/frappe-api-client branch from dba5c33 to 481fc7f Compare May 12, 2026 18:57
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.

[PoW] Architecture: Typed Frappe API Client and Secure Authentication Layer

1 participant