Skip to content

Commit d396db6

Browse files
committed
docs,fix: Add Software Requirements Specification using Typst and fix authentication BLoC.
1 parent 9eaf8ac commit d396db6

2 files changed

Lines changed: 223 additions & 5 deletions

File tree

docs/srs.typ

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#let primary-color = rgb("#3730A3")
2+
#let secondary-color = rgb("#4338CA")
3+
#let text-color = rgb("#1F2937")
4+
5+
#set document(title: "Software Requirements Specification - Monet", author: "Rafi Abiyyu Airlangga")
6+
7+
#set page(
8+
footer: context {
9+
if counter(page).get().first() > 1 [
10+
#set text(10pt, fill: luma(120), font: "Times New Roman")
11+
#align(center)[#counter(page).display("1")]
12+
]
13+
},
14+
header: context {
15+
if counter(page).get().first() > 1 [
16+
#set text(8pt, fill: luma(120), font: "Times New Roman")
17+
#grid(
18+
columns: (1fr, 1fr),
19+
align(left)[*Monet* - Software Requirements Specification], align(right)[IEEE 830 / ISO/IEC/IEEE 29148],
20+
)
21+
#v(-0.5em)
22+
#line(length: 100%, stroke: 0.5pt + luma(200))
23+
]
24+
},
25+
margin: (x: 2.54cm, y: 2.54cm),
26+
paper: "a4",
27+
)
28+
29+
#set text(font: "Times New Roman", size: 12pt, fill: text-color)
30+
#set par(justify: true, leading: 1.5em)
31+
#set heading(numbering: "1.1")
32+
33+
#show heading: it => [
34+
#set text(fill: primary-color, weight: "bold")
35+
#block(spacing: 1.5em, it)
36+
]
37+
38+
#let callout(body) = block(
39+
fill: rgb("#EEF2FF"),
40+
stroke: (left: 4pt + primary-color),
41+
inset: 12pt,
42+
radius: 4pt,
43+
width: 100%,
44+
[#set text(size: 11pt); #body],
45+
)
46+
47+
#align(center)[
48+
#set image(
49+
alt: "Cover of Monet's Software Requirements Specification",
50+
fit: "cover",
51+
)
52+
]
53+
#pagebreak()
54+
55+
#outline(title: [Table of Contents], depth: 2)
56+
#pagebreak()
57+
58+
= Introduction
59+
60+
== Purpose
61+
The purpose of this Software Requirements Specification (SRS) is to provide a comprehensive and detailed overview of the software requirements for Monet, a personal finance tracker equipped with Near Field Communication (NFC) banking card integration. This document serves as the definitive baseline for developers, system architects, quality assurance teams, and project stakeholders to ensure alignment on product capabilities and technical constraints throughout the software development lifecycle.
62+
63+
== Scope of Product
64+
Monet is a cross-platform mobile application designed to simplify personal financial management. The system allows users to intuitively track their expenses, visualize budgets, and manage financial categories.
65+
66+
The core differentiator of Monet is its hardware integration: the application utilizes smartphone NFC sensors to read banking card metadata, enabling automated expense logging and card registration. The application ecosystem is comprised of a frontend client developed in Flutter and a high-performance backend API engineered using Golang.
67+
68+
== Glossary, Acronyms, and Abbreviations
69+
#table(
70+
columns: (25%, 75%),
71+
stroke: 0.5pt + luma(200),
72+
fill: (col, row) => if row == 0 { primary-color.lighten(85%) } else { none },
73+
[*Term / Acronym*], [*Definition*],
74+
[*API*], [Application Programming Interface. A set of protocols for backend communication.],
75+
[*BLoC*],
76+
[Business Logic Component. A state management pattern utilized in the Flutter frontend to separate presentation from business logic.],
77+
78+
[*JWT*],
79+
[JSON Web Token. A compact, URL-safe means of representing claims to be transferred between two parties, used for secure user authentication.],
80+
81+
[*NFC*],
82+
[Near Field Communication. A set of communication protocols enabling two electronic devices to establish communication by bringing them within 4 cm of each other.],
83+
84+
[*UID*], [Unique Identifier. A sequence of characters securely identifying an NFC-enabled banking card.],
85+
)
86+
87+
== Standard References
88+
This document conforms strictly to the structural and analytical guidelines established by the IEEE 830-1998 and ISO/IEC/IEEE 29148:2018 standards for software requirements specifications.
89+
90+
#pagebreak()
91+
92+
= Overall Description
93+
94+
== Product Perspective
95+
Monet operates as a multi-tier client-server architecture. It is an independent product that relies on the seamless interaction of three primary components:
96+
1. *Frontend Client (Mobile):* A cross-platform mobile application compiled for Android and iOS using Flutter. It handles the user interface, local routing via GoRouter, state management, and direct hardware interactions with the device's NFC sensor.
97+
2. *Backend API (Server):* A RESTful API built with Golang using the Gin Framework. It exposes endpoints prefixed with `/api/v1` to handle authentication, transaction processing, and analytics retrieval.
98+
3. *Database Layer:* A MySQL relational database interacting with the backend via the GORM library to ensure data persistence, integrity, and relational mapping of user profiles, registered cards, and transaction logs.
99+
100+
== User Characteristics & Personas
101+
Monet is designed to accommodate users with varying levels of financial literacy and technical expertise.
102+
- *The Everyday Consumer:* An individual looking for a fast, automated way to log daily transactions without tedious manual data entry. They expect a clean, responsive UI where reading a card is as simple as tapping it against their phone.
103+
- *The Power Budgeter:* A highly analytical user who relies on statistical breakdowns, categorizations, and visual charts (rendered via `fl_chart`) to maintain strict control over their financial health.
104+
105+
== Design and Implementation Constraints
106+
#callout[
107+
*Note on Financial Compliance:* As a personal finance tracker handling banking card metadata, Monet must adhere strictly to security best practices, even if it does not directly process payment gateways.
108+
]
109+
110+
- *Hardware Dependency:* The automated card reading functionality strictly requires the user's mobile device to be equipped with a functioning NFC module. Devices without NFC will be limited to manual entry features.
111+
- *Security & Encryption:* Sensitive data, such as JWT authentication tokens, must be stored client-side using Secure Storage. The backend must enforce password hashing utilizing Bcrypt before storing credentials in the MySQL database.
112+
- *Network Requirements:* While the mobile client may cache data locally, finalizing NFC metadata registration and syncing analytical data requires a stable internet connection to communicate with the backend API.
113+
114+
= External Interface Requirements
115+
116+
== User Interfaces
117+
The user interface of Monet is built using the Flutter framework, ensuring a native-like, responsive experience across both Android and iOS devices. The application utilizes a modern, accessible design language emphasizing clarity in financial data visualization. Routing is managed via `GoRouter` for seamless navigation.
118+
119+
Key screens include:
120+
- *Authentication Screens:* Login (`/login`), Register (`/register`), OTP Verification (`/otp`), and Password Recovery (`/forgot-password`, `/reset-password`).
121+
- *Dashboard / Home (`/home`):* A unified overview displaying current balance, recent transactions, and quick-access buttons.
122+
- *NFC Scanner (`/nfc-scanner`):* A dedicated UI state prompting the user to tap their banking card against the device, featuring visual and haptic feedback loops.
123+
- *Expense Tracker & Analytics (`/expense-tracker`):* Comprehensive financial breakdowns utilizing `fl_chart` for rendering interactive pie charts and bar graphs.
124+
125+
#figure(
126+
rect(width: 85%, height: 180pt, fill: luma(245), stroke: (dash: "dashed", paint: luma(150), thickness: 1pt))[
127+
#align(center + horizon)[
128+
#text(fill: luma(100), style: "italic")[Placeholder: Home Dashboard & NFC Scanner Prototype] \
129+
#text(size: 10pt, fill: luma(150))[Replace this block with: `#image("path/to/prototype.png")`]
130+
]
131+
],
132+
caption: [Monet User Interface Prototypes],
133+
)
134+
135+
== Hardware Interfaces
136+
The core hardware interface is the smartphone's built-in *Near Field Communication (NFC) sensor*.
137+
- The application will interact with the NFC hardware utilizing platform-specific channels (via Flutter NFC plugins).
138+
- It expects to read cards adhering to ISO/IEC 14443 Type A/B standards.
139+
- The hardware interface must be capable of extracting the public UID (Unique Identifier) and available unencrypted metadata from the banking card without attempting to execute secure payment transactions (EMV protocols).
140+
141+
== Software Interfaces
142+
The mobile client communicates securely with the Golang backend through a RESTful API architecture. All endpoints are prefixed with `/api/v1` and expect `application/json` payload formats.
143+
144+
#table(
145+
columns: (30%, 20%, 50%),
146+
stroke: 0.5pt + luma(200),
147+
fill: (col, row) => if row == 0 { primary-color.lighten(85%) } else { none },
148+
[*Endpoint Contract*], [*HTTP Method*], [*Description*],
149+
[`/auth/login`], [POST], [Authenticates user credentials and returns a secure JWT for session management.],
150+
[`/cards`], [GET / POST], [Retrieves registered NFC cards or registers a new card UID to the user's profile.],
151+
[`/transactions`], [GET / POST], [Fetches transaction history or logs a new manual/NFC-triggered expense.],
152+
[`/analytics/summary`], [GET], [Provides aggregated statistical data for `fl_chart` visualization on the client.],
153+
)
154+
155+
== Communications Interfaces
156+
- *Network Protocol:* All client-server communication must occur over HTTPS utilizing TLS 1.2 or higher to ensure the encryption of financial metadata and authentication tokens in transit.
157+
- *Authentication Delivery:* The API utilizes Bearer Token authorization via HTTP Headers (`Authorization: Bearer <JWT>`).
158+
159+
#pagebreak()
160+
161+
= System Features & Functional Requirements
162+
163+
== Authentication & User Profile Module
164+
*Description:* This module manages user identity, onboarding, and secure access to the application.
165+
*Functional Requirements:*
166+
- *FR-1.1:* The system shall allow users to register an account using an email address, password, and secure OTP verification.
167+
- *FR-1.2:* The system shall authenticate users and generate a JWT payload containing user claims with a predefined expiration time.
168+
- *FR-1.3:* The system shall provide a mechanism for users to securely reset forgotten passwords via email-delivered links or OTPs.
169+
- *FR-1.4:* The client application shall store the active session JWT securely utilizing platform-specific Secure Storage (Keystore for Android, Keychain for iOS).
170+
171+
== NFC Card Management Module
172+
*Description:* This feature enables users to link their physical banking or e-money cards to the application via NFC scanning.
173+
*Functional Requirements:*
174+
- *FR-2.1:* The system shall initiate an NFC reading session when the user accesses the `/nfc-scanner` route.
175+
- *FR-2.2:* The system shall extract the card's UID and allow the user to assign a custom alias (e.g., "Main Debit", "Transport Card").
176+
- *FR-2.3:* The system shall prevent the duplication of identical card UIDs within a single user's profile.
177+
- *FR-2.4:* The backend (`/api/v1/cards/:id`) shall allow users to retrieve, update, or detach (delete) registered cards.
178+
179+
== Transaction & Expense Logging Module
180+
*Description:* The core tracking capability, allowing for both manual data entry and accelerated, automated entry triggered by NFC events.
181+
*Functional Requirements:*
182+
- *FR-3.1:* The system shall allow users to manually input a transaction, specifying the amount, date, category, and optional notes.
183+
- *FR-3.2 (NFC Automation):* Upon tapping a registered NFC card, the system shall automatically open a pre-filled transaction form mapped to that specific card, requiring the user only to input the expense amount.
184+
- *FR-3.3:* All logged transactions shall be synchronized with the Golang backend and stored relationally in the MySQL database via GORM.
185+
186+
== Budgeting, Categories & Analytics Module
187+
*Description:* Provides users with insight into their spending habits through logical categorization and graphical analysis.
188+
*Functional Requirements:*
189+
- *FR-4.1:* The system shall provide a default set of expense categories (e.g., Food, Transport, Utilities) while allowing the creation of custom categories via `/api/v1/categories`.
190+
- *FR-4.2:* Users shall be able to establish monthly spending limits (Budgets) per category.
191+
- *FR-4.3:* The backend shall aggregate transaction data and expose it via the `/api/v1/analytics/summary` endpoint.
192+
- *FR-4.4:* The Flutter client shall consume the analytics payload and render dynamic graphical representations (such as pie charts for category breakdowns and line charts for daily spending trends).
193+
194+
#pagebreak()
195+
196+
= Non-Functional Requirements
197+
198+
== Security Requirements
199+
Given the sensitive nature of personal financial data, Monet must enforce robust security measures at both the client and server levels:
200+
- *Data in Transit:* All communications between the Flutter client and the Golang backend must be encrypted using HTTPS with TLS 1.2 or higher.
201+
- *Data at Rest (Server):* User passwords must never be stored in plain text. The backend must hash and salt all passwords utilizing the `Bcrypt` algorithm before committing them to the MySQL database.
202+
- *Session Management:* API access must be secured using JSON Web Tokens (JWT). Tokens must have a clearly defined expiration time to prevent session hijacking.
203+
- *Client-Side Security:* The mobile application must not store sensitive credentials (like JWTs or raw user passwords) in standard shared preferences. It must utilize platform-specific secure enclaves: *Keychain* for iOS and *EncryptedSharedPreferences/Keystore* for Android.
204+
205+
== Performance Requirements
206+
To ensure a frictionless user experience, particularly during hardware interactions, the system must adhere to the following performance benchmarks:
207+
- *NFC Latency:* The smartphone's NFC sensor must detect, read the card UID, and trigger the corresponding transaction UI within *1 second* of a successful physical tap.
208+
- *API Response Time:* Under normal operating conditions, all standard backend REST API endpoints (e.g., `/api/v1/transactions`) must return a response within *500 milliseconds*.
209+
- *UI Smoothness:* The Flutter frontend must maintain a stable render rate of 60 frames per second (FPS) to ensure smooth transitions and animations, especially when rendering complex analytics via `fl_chart`.
210+
211+
== Availability and Reliability
212+
- *Uptime:* The Golang backend API and MySQL database infrastructure should be architected to achieve an availability target of 99.9% (excluding scheduled maintenance windows).
213+
- *Graceful Degradation (Offline Mode):* If the mobile device loses network connectivity, the application should not crash. It must cache pending transactions locally and synchronize them with the backend automatically once the network is restored.
214+
- *Hardware Fallback:* If the user's device lacks an NFC module, or if the sensor is damaged, the application must remain fully usable by seamlessly defaulting to the manual transaction entry mode.
215+
216+
== Maintainability and Scalability
217+
- *Frontend Architecture:* The client codebase must strictly adhere to the *BLoC (Business Logic Component)* pattern. This ensures a clean separation of concerns between UI rendering and financial business logic, facilitating easier updates and bug fixes.
218+
- *Backend Scalability:* The Golang API must be stateless (relying on JWTs for authorization) to allow for horizontal scaling. The system should be able to handle an increased load of concurrent users and transaction logging without significant architectural changes.

lib/features/auth/bloc/auth_bloc.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
2121
await authRepository.forgotPassword(event.email);
2222
emit(AuthSuccess(message: 'Password reset instructions have been sent to your email.'));
2323
} catch (e) {
24-
emit(AuthError(e.toString()));
24+
emit(AuthError(e.toString().replaceAll('Exception: ', '')));
2525
}
2626
}
2727

@@ -32,7 +32,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
3232
await authRepository.login(event.request);
3333
emit(AuthSuccess(message: 'Login successful!'));
3434
} catch (e) {
35-
emit(AuthError(e.toString()));
35+
emit(AuthError(e.toString().replaceAll('Exception: ', '')));
3636
}
3737
}
3838

@@ -43,7 +43,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
4343
await authRepository.verifyOtp(event.request);
4444
emit(AuthSuccess(message: 'OTP Verified Successfully!'));
4545
} catch (e) {
46-
emit(AuthError(e.toString()));
46+
emit(AuthError(e.toString().replaceAll('Exception: ', '')));
4747
}
4848
}
4949

@@ -57,7 +57,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
5757
message: 'Registration successful! Please check your email.',
5858
));
5959
} catch (e) {
60-
emit(AuthError(e.toString()));
60+
emit(AuthError(e.toString().replaceAll('Exception: ', '')));
6161
}
6262
}
6363

@@ -68,7 +68,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
6868
await authRepository.resetPassword(event.token, event.newPassword);
6969
emit(AuthSuccess(message: 'Your password has been successfully reset. Please log in.'));
7070
} catch (e) {
71-
emit(AuthError(e.toString()));
71+
emit(AuthError(e.toString().replaceAll('Exception: ', '')));
7272
}
7373
}
7474
}

0 commit comments

Comments
 (0)