Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ca87420
docs: add CRUD API implementation plan
Sakeeb91 Oct 10, 2025
da94700
backend: scaffold FastAPI application structure
Sakeeb91 Oct 10, 2025
7d83931
backend: define ORM models for core entities
Sakeeb91 Oct 10, 2025
e286e39
backend: add Pydantic schemas with validation metadata
Sakeeb91 Oct 10, 2025
1a209ea
backend: implement async repositories for CRUD
Sakeeb91 Oct 10, 2025
444db13
backend: add service layer with business rules
Sakeeb91 Oct 10, 2025
671754b
backend: expose CRUD API routers with error handling
Sakeeb91 Oct 10, 2025
05f2355
tests: cover project and resource workflows
Sakeeb91 Oct 10, 2025
ebe6f1d
docs: document backend CRUD service usage
Sakeeb91 Oct 10, 2025
54efe7e
chore: add dev env template and sample data seed script
Sakeeb91 Oct 10, 2025
8247367
backend: improve config compatibility and add test harness
Sakeeb91 Oct 10, 2025
a793f5d
feat: Implement real-time alert engine and CI pipeline
Sakeeb91 Oct 10, 2025
ddf1f6c
Revert "feat: Implement real-time alert engine and CI pipeline"
Sakeeb91 Oct 10, 2025
4ab99c5
feat: Implement real-time alert engine and CI pipeline
Sakeeb91 Oct 10, 2025
e19c9d1
feat: Implement user authentication and JWT (closes #4)
Sakeeb91 Oct 11, 2025
67eca71
feat(iot): initial IoT layer setup with Flask ingestion server and ES…
Sakeeb91 Oct 11, 2025
1814280
feat: Add Alembic for database migrations and versioning
Sakeeb91 Oct 11, 2025
e20dcf3
Merge pull request #13 from Sakeeb91/feature/issue-3
RonaldRonnie Oct 14, 2025
3a771ef
Fix CI: enforce Pydantic v2
RonaldRonnie Oct 14, 2025
ae4be88
Fix: remove conflicting Pydantic version constraint
RonaldRonnie Oct 14, 2025
4cfc26e
Update requirements.txt
RonaldRonnie Oct 14, 2025
9252a43
Update ci.yml
RonaldRonnie Oct 14, 2025
29bb7c7
Update README.md
kmuwanga83 Oct 15, 2025
0231e91
Update README.md
kmuwanga83 Oct 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
name: Run Backend Tests
runs-on: ubuntu-latest

steps:
# Step 1: Checkout repository
- name: Checkout code
uses: actions/checkout@v4

# Step 2: Set up Python 3.11
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

# Step 3: Upgrade pip and install dependencies cleanly
- name: Install dependencies
run: |
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip wheel setuptools
pip install --no-cache-dir -r backend/requirements.txt

# Step 4: Run tests with pytest
- name: Run tests
run: |
source .venv/bin/activate
pytest backend/tests -v --disable-warnings

# Step 5: (Optional) Upload test results (useful for debugging failures)
- name: Upload pytest logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: pytest-logs
path: .pytest_cache/
134 changes: 97 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,128 @@

## Project Summary

LifeLine-ICT is a system for … (brief description: what problem is solved, who uses it, main components: IoT, backend, GIS, frontend, deployment)
LifeLine-ICT is a digital infrastructure management platform that supports the
Uganda University ICT department. The system tracks strategic ICT projects,
inventory assets, IoT deployments, and the maintenance activities that keep
digital services reliable for students and researchers. The repository contains
code for the IoT device layer, the backend APIs, and supporting documentation so
faculties can adapt the platform to their own campuses.

### High-Level Architecture

Brief overview of how iot, backend, gis, frontend interact. Maybe include a diagram (link to `docs/architecture.md`).
The solution comprises five collaborating layers:

- **IoT layer** – ESP32-based sensor nodes send telemetry to a lightweight Flask
logger (`iot/logging`).
- **Backend APIs** – A FastAPI service (`backend/app`) exposes CRUD endpoints for
projects, resources, locations, maintenance tickets, and sensor sites.
- **GIS & Analytics** – Future modules will combine telemetry and asset data to
power dashboards and risk assessments.
- **Frontend** – Web dashboards and mobile apps consume the backend APIs.
- **Deployment** – Infrastructure-as-code scripts will package the stack for on
campus or cloud hosting.

Consult `docs/backend_crud_plan.md` for the architectural rationale that guided
issue `#5` (CRUD API implementation).

### Module Overview

- **iot/** – code for sensors, gateways, device firmware
- **backend/** – APIs, business logic, data storage
- **gis/** – geospatial processing, map generation, spatial analyses
- **frontend/** – user interfaces, dashboards, maps
- **deployment/** – infrastructure as code, deployment manifests, Docker, etc.
- **docs/** – project documentation
- `iot/` – Firmware sketches and logging scripts for field sensors.
- `backend/` – FastAPI application, domain models, services, and tests.
- `docs/` – Supplemental guides and design notes.
- Additional directories (frontend, gis, deployment) will be filled as the
broader initiative matures.

## Getting Started
## Backend Service (Issue #5 Deliverable)

### Prerequisites

List required tools (e.g. Node.js, Python, Docker, etc.)
- Python 3.11+
- `pip` or `uv` for dependency management
- Optional: `uvicorn` CLI for local development

### Local Setup
### Installation

Steps to clone, install dependencies, run each module (iot, backend, frontend, etc.)
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r backend/requirements.txt
```

### Running Tests / Building
### Running the API

Commands to run tests, linting, build all modules, etc.
```bash
uvicorn backend.app.main:app --reload
```

### Deployment
The service listens on `http://127.0.0.1:8000` by default. OpenAPI
documentation is available at `http://127.0.0.1:8000/docs`.

Instructions (or link to docs) to deploy to staging / production environments.
### Core Endpoints

## Contributing
| Entity | Base Path | Notes |
| --- | --- | --- |
| Projects | `/api/v1/projects` | CRUD with pagination & search |
| ICT Resources | `/api/v1/resources` | Validates project/location references and enforces ticket rules |
| Locations | `/api/v1/locations` | CRUD with geo metadata |
| Maintenance Tickets | `/api/v1/maintenance-tickets` | Requires resolution metadata when closing a ticket |
| Sensor Sites | `/api/v1/sensor-sites` | Links IoT deployments to resources, projects, and locations |

We welcome contributions! Please follow these guidelines:
Each list endpoint accepts `limit`, `offset`, and `search` query parameters and
returns pagination metadata to keep API consumers informed.

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature`
3. Commit changes with clear, descriptive messages
4. Write tests where applicable
5. Ensure linting and tests pass
6. Submit a pull request
### Running Tests

### Coding Standards
```bash
pytest backend/tests
```

- Language(s) used (e.g. Python, JavaScript, etc.)
- Style/lint rules (e.g. `eslint`, `flake8`, etc.)
- Commit message style (e.g. Conventional Commits)
The suite provisions an in-memory SQLite database and covers both service-level
rules (such as blocking resource deletion while tickets remain open) and API
contracts.

### Issue / PR Workflow
### Database Migrations

- Create or reference an issue before starting major work
- Keep pull requests small and focused
- Use descriptive titles and references to issues
- Request reviews, respond to feedback
This project uses [Alembic](https://alembic.sqlalchemy.org/en/latest/) for database migrations.

## License
To create a new migration, run:

```bash
alembic revision --autogenerate -m "<migration_message>"
```

To apply migrations to the database, run:

```bash
alembic upgrade head
```

### Data Model Highlights

State your license (MIT, Apache, etc.).
The backend models capture the following relationships:

- Projects aggregate ICT resources and sensor sites.
- Resources optionally link to projects and locations, and can host sensor
deployments.
- Maintenance tickets belong to resources and require closure notes when marked
resolved.

Consult the service-layer docstrings for detailed business rules and
institutional context.

## Contributing

1. Create an issue or pick an existing one (see `issues.md`).
2. Branch from `main`: `git checkout -b feature/your-feature`.
3. Follow the layered structure (`api`, `services`, `repositories`, `models`) to
keep contributions organised.
4. Write tests and run `pytest backend/tests` before opening a pull request.
5. Document behaviour changes in code docstrings or the project docs.

## License

## Contact / Maintainers
MIT, Apache

List maintainers, contact paths, etc.
## Maintainers

Muwanga Erasto Kosea, Ouma Ronald
6 changes: 6 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Default configuration for local development.
LIFELINE_DATABASE_URL=sqlite+aiosqlite:///./lifeline.db
LIFELINE_API_VERSION=0.1.0
LIFELINE_CONTACT_EMAIL=ict-support@lifeline.example.edu
LIFELINE_PAGINATION_DEFAULT_LIMIT=20
LIFELINE_PAGINATION_MAX_LIMIT=100
1 change: 1 addition & 0 deletions backend/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""LifeLine-ICT backend package."""
147 changes: 147 additions & 0 deletions backend/alembic.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# A generic, single database configuration.

[alembic]
# path to migration scripts.
# this is typically a path given in POSIX (e.g. forward slashes)
# format, relative to the token %(here)s which refers to the location of this
# ini file
script_location = %(here)s/migrations

# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# Uncomment the line below if you want the files to be prepended with date and time
# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
# for all available tokens
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s

# sys.path path, will be prepended to sys.path if present.
# defaults to the current working directory. for multiple paths, the path separator
# is defined by "path_separator" below.
prepend_sys_path = .


# timezone to use when rendering the date within the migration file
# as well as the filename.
# If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library.
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
# string value is passed to ZoneInfo()
# leave blank for localtime
# timezone =

# max length of characters to apply to the "slug" field
# truncate_slug_length = 40

# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false

# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false

# version location specification; This defaults
# to <script_location>/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
# The path separator used here should be the separator specified by "path_separator"
# below.
# version_locations = %(here)s/bar:%(here)s/bat:%(here)s/alembic/versions

# path_separator; This indicates what character is used to split lists of file
# paths, including version_locations and prepend_sys_path within configparser
# files such as alembic.ini.
# The default rendered in new alembic.ini files is "os", which uses os.pathsep
# to provide os-dependent path splitting.
#
# Note that in order to support legacy alembic.ini files, this default does NOT
# take place if path_separator is not present in alembic.ini. If this
# option is omitted entirely, fallback logic is as follows:
#
# 1. Parsing of the version_locations option falls back to using the legacy
# "version_path_separator" key, which if absent then falls back to the legacy
# behavior of splitting on spaces and/or commas.
# 2. Parsing of the prepend_sys_path option falls back to the legacy
# behavior of splitting on spaces, commas, or colons.
#
# Valid values for path_separator are:
#
# path_separator = :
# path_separator = ;
# path_separator = space
# path_separator = newline
#
# Use os.pathsep. Default configuration used for new projects.
path_separator = os

# set to 'true' to search source files recursively
# in each "version_locations" directory
# new in Alembic version 1.10
# recursive_version_locations = false

# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8

# database URL. This is consumed by the user-maintained env.py script only.
# other means of configuring database URLs may be customized within the env.py
# file.
sqlalchemy.url = %(LIFELINE_DATABASE_URL_ALEMBIC)s


[post_write_hooks]
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples

# format using "black" - use the console_scripts runner, against the "black" entrypoint
# hooks = black
# black.type = console_scripts
# black.entrypoint = black
# black.options = -l 79 REVISION_SCRIPT_FILENAME

# lint with attempts to fix using "ruff" - use the module runner, against the "ruff" module
# hooks = ruff
# ruff.type = module
# ruff.module = ruff
# ruff.options = check --fix REVISION_SCRIPT_FILENAME

# Alternatively, use the exec runner to execute a binary found on your PATH
# hooks = ruff
# ruff.type = exec
# ruff.executable = ruff
# ruff.options = check --fix REVISION_SCRIPT_FILENAME

# Logging configuration. This is also consumed by the user-maintained
# env.py script only.
[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = WARNING
handlers = console
qualname =

[logger_sqlalchemy]
level = WARNING
handlers =
qualname = sqlalchemy.engine

[logger_alembic]
level = INFO
handlers =
qualname = alembic

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
13 changes: 13 additions & 0 deletions backend/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""
LifeLine-ICT backend application package.

This module intentionally exposes the application factory to keep imports
concise throughout the codebase. The backend follows a layered architecture
documented in ``docs/backend_crud_plan.md`` where API routers, services,
repositories, and models are separated to match the university's governance
expectations.
"""

from .main import create_app

__all__ = ["create_app"]
Loading
Loading