Technion, Faculty of Computer Science
2025-2026-Winter Semester - 02340311 - Yearly Project in Software Eng.-Stage A
2025-2026-Spring Semester - 02340312 - Yearly Project in Software Eng.-Stage B
Supervisor: Daria Bebin
Team members:
GhostHouses is a municipal web system for tracking vacant and rehabilitation buildings for Haifa Municipality. It supports structured building data, import/export workflows, audit logs, GIS map integration, and presentation-ready building cards. The system is built with a .NET backend, React frontend, PostgreSQL database, and Docker Compose deployment.
- Create, edit, delete, and view building details with categorized fields.
- Mandatory field validation and conditional business rules.
- Advanced filters, date filters, and sortable table columns.
- Building actions for Excel export, building-card export, GIS map opening, and logs.
- Supports one image per building for details and building-card export.
- Immutable audit trail for building and user actions.
- Per-field change tracking with old/new values.
- Filters by date, user, and field data.
- Excel import with staged validation and conflict resolution.
- Excel export based on the current UI field order and selected rows.
- Building-card PPTX export for one or multiple buildings.
- GIS snapshots are inserted into building cards when the building can be located.
- GIS map page using Haifa Municipality map services.
- Buildings can be opened directly on the GIS map from the Buildings page.
- All database buildings with GIS location data are shown on the map.
- Users can select an area on the map and view/export matching system buildings.
- GIS is an active integration, not a mock.
- User management for Viewer, Editor, and Admin roles.
- Login flow with mocked OTP boundary ready for a real provider after handoff.
git clone https://github.com/bbdaria/GhostHouses.git
cd GhostHouses/project
cp .env.example .env
# Fill .env with the real secrets from the team shared drive / secure handoff mail.
docker compose up -d --buildFor a full clean reset:
cd project
docker compose down -v && docker compose up -d --buildBefore running, make sure these local files exist:
project/.envwith the real database, pgAdmin, and JWT secrets.project/certs/dev.crtandproject/certs/dev.keyfor HTTPS.
Do not commit project/.env or anything under project/certs/. They are ignored by git and should be shared only through the team shared drive or secure handoff mail. See project/HANDOFF_SECRETS.md for exact file locations.
On a clean database, the backend creates one initial administrator account: admin / admin. Give this account only to the department owner during handoff. They can create the real municipality users and then change or disable the initial admin account.
Poster files are stored under docs/submissions/stage-b/poster/.
- Required template:
docs/submissions/stage-b/poster/Yearly Poster Pattern 97x67.pptx - Project's poster:
docs/submissions/stage-b/poster/GhostHouses_Poster.pptx
Poster assets are organized under:
docs/submissions/stage-b/poster/assets/logo/docs/submissions/stage-b/poster/assets/title-tagline/docs/submissions/stage-b/poster/assets/description/docs/submissions/stage-b/poster/assets/grid/docs/submissions/stage-b/poster/assets/team/
Presentation source files are stored under docs/submissions/stage-b/presentation/.
- Beamer source:
docs/submissions/stage-b/presentation/StageB_Presentation.tex - Rendered PDF:
docs/submissions/stage-b/presentation/StageB_Presentation.pdf
The diagram shows how our main actors connect to permissions, use cases, GitHub User Story issues, and the sprint branches where the work was delivered. It is written in UML 2.5.1 style and rendered with PlantUML.
- Source:
docs/submissions/stage-b/uml/use-cases/presentation/use_cases_to_sprints.puml - Rendered image:
docs/submissions/stage-b/uml/use-cases/presentation/use_cases_to_sprints.png - Vector render:
docs/submissions/stage-b/uml/use-cases/presentation/use_cases_to_sprints.pdf
The diagram is intentionally presentation-level: it keeps the main flow readable as actors -> permissions -> use cases -> User Story issues -> sprint branches. Detailed implementation sub-issues, time-tracked comments, and branch history remain traceable in GitHub.
We use the class UML to explain the main architecture decisions: what we kept abstract, what we implemented concretely, and why. It is written in UML 2.5.1 style and rendered with PlantUML.
- Source:
docs/submissions/stage-b/uml/class/class_diagram.puml - Rendered image:
docs/submissions/stage-b/uml/class/class_diagram.png - Vector render:
docs/submissions/stage-b/uml/class/class_diagram.pdf
What is abstract:
- Controller reuse is abstracted through
ApiControllerBase, which centralizes shared authenticated API behavior. - Replaceable service contracts isolate important extension points:
ITokenService,ITwoFactorService,IAuditService, andIGisSnapshotService. - GIS snapshot generation is behind
IGisSnapshotService, so a different GIS provider can replace ArcGIS without changing controllers or building-card export flow. - OTP is behind
ITwoFactorService, so the mocked OTP delivery can be replaced by a real SMS/email provider after handoff. - Building and street validation are centralized in
BuildingRulesandStreetRules, so manual editing and Excel import follow the same business rules.
Where we committed to concrete technology:
- PostgreSQL is the concrete database, accessed through EF Core and
AppDbContext. - ASP.NET Core is the backend API framework.
- React/Vite is the frontend implementation.
- ArcGIS is the active GIS provider for the municipality map and building-card snapshots.
- Docker Compose is the deployment unit for frontend, backend, PostgreSQL, and pgAdmin.
Why this split fits the project:
- Stable project decisions, such as PostgreSQL, ASP.NET Core, React, and Docker Compose, are concrete because they define the runtime system.
- Riskier or more likely-to-change boundaries, such as OTP delivery, GIS provider, audit behavior, and token generation, are kept behind interfaces so they can be replaced without rewriting the full application.
We use the deployment UML to explain how GhostHouses is intended to run inside the municipality environment, what blocked the deployment, and what we prepared to move it forward. It is written in UML 2.5.1 style and rendered with PlantUML.
- Source:
docs/submissions/stage-b/uml/deployment/deployment_environment.puml - Rendered image:
docs/submissions/stage-b/uml/deployment/deployment_environment.png - Vector render:
docs/submissions/stage-b/uml/deployment/deployment_environment.pdf - Deployment User Story: Issue #94
What the deployment UML shows:
- Municipality user and IT admin workstations connect to the deployed system through browser execution environments.
- The frontend, backend, PostgreSQL, and pgAdmin run as Docker execution environments on the municipality Windows Server VM.
- Deployed artifacts are shown inside their runtime containers.
- Communication paths show HTTPS, HTTP, PostgreSQL, and the relevant Docker networks without exposing port labels in the UML diagram.
- The backend has outbound HTTPS access to the Haifa Municipality GIS / ArcGIS API.
- OTP remains mocked inside the backend for handoff, so there is no external OTP provider dependency.
Main deployment blocker:
- The target environment is a municipality Windows Server VM.
- Running the delivered Docker Compose stack on that VM depends on Docker/WSL support, which may require nested virtualization approval from municipality security/IT.
How we handled it:
- Prepared a one-command Docker Compose deployment from
project/. - Documented required ports, software dependencies, hardware expectations, secrets, and certificates.
- Prepared alternatives with the supervisor in case nested virtualization is not approved.
- Continued written communication with the client side, dev team, IT/security contacts, and supervisors to move deployment forward professionally.
Deployment is handled through one top-level Docker Compose file: project/docker-compose.yml.
From the project/ folder, one command builds and starts the full system:
docker compose down -v && docker compose up -d --buildThis deployment path is intentionally simple and repeatable:
- One command runs the full stack: frontend, backend, PostgreSQL, and pgAdmin.
- Docker Compose builds the project services and pulls required public images when needed.
- PostgreSQL starts with a health check before the backend is used.
- Docker networks are created automatically with the intended isolation:
app-net,db-net, andadmin-net. down -vresets the database and pgAdmin volumes, which gives a clean deployment state when needed.- Required local files are documented:
project/.env,project/certs/dev.crt, andproject/certs/dev.key.
Ports and Docker networking:
- Frontend (Nginx):
https://localhost:443, host port 443 to container 443. - Backend (ASP.NET Core): internal only,
http://backend:8080, no host port mapping. - Database (PostgreSQL): internal only,
db:5432, no host port mapping. - pgAdmin:
https://localhost:8443, host port 8443 to container 443. - Networks:
app-netfor frontend/backend,db-netfor backend/database, andadmin-netfor pgAdmin/database.
This section documents the minimum environment needed to deploy GhostHouses and links each requirement to the runtime design.
The Stage B deployment UML is written in UML 2.5.1 style and rendered with PlantUML.
- Source:
docs/submissions/stage-b/uml/deployment/deployment_environment.puml - Rendered image:
docs/submissions/stage-b/uml/deployment/deployment_environment.png - Vector render:
docs/submissions/stage-b/uml/deployment/deployment_environment.pdf
The diagram shows:
- Municipality user and IT admin workstations access the deployed system through browser execution environments.
- The frontend container serves the React application through Nginx.
- The backend container runs the ASP.NET Core API internally and is not exposed directly outside Docker.
- PostgreSQL runs internally and is not exposed directly outside Docker.
- pgAdmin is separated for IT/database administration.
- Docker communication paths are labeled by purpose:
app-net,db-net, andadmin-net. - The backend has outbound HTTPS access to the public Haifa Municipality GIS / ArcGIS API.
- OTP is mocked inside the backend for this delivery, so there is no external OTP provider dependency.
GhostHouses is deployed through Docker Compose, so the server does not need manual installation of .NET, Node.js, PostgreSQL, or Nginx. Those dependencies are provided by Docker images during build and runtime.
| Dependency | Version / Source | Why it is needed |
|---|---|---|
| Windows Server VM | Municipality-provided server | Target deployment host |
| Docker + Docker Compose | Installed on the server | Builds and runs the full application stack |
| WSL 2 / nested virtualization | Needed if Docker Desktop is used on a Windows Server VM | Required for Linux containers on Docker Desktop |
| PostgreSQL image | postgres:16 |
Application database |
| pgAdmin image | dpage/pgadmin4:latest |
Database administration UI for IT/DB admins |
| .NET SDK image | mcr.microsoft.com/dotnet/sdk:8.0 |
Builds the ASP.NET Core backend |
| ASP.NET runtime image | mcr.microsoft.com/dotnet/aspnet:8.0 |
Runs the backend container |
| Node image | node:20 |
Builds the React/Vite frontend |
| Nginx image | nginx:alpine |
Serves the built frontend over HTTPS |
| TLS certificate and key | project/certs/dev.crt, project/certs/dev.key |
Enables HTTPS for frontend and pgAdmin |
| Environment file | project/.env |
Provides database, pgAdmin, and JWT configuration |
| Outbound HTTPS access | Port 443 | Pulls Docker images during build/deployment and calls the Haifa Municipality GIS API at runtime |
Recommended deployment VM:
| Resource | Requirement |
|---|---|
| CPU | 4 vCPU |
| RAM | 8 GB |
| Storage | 100 GB SSD |
| OS | Windows Server VM |
| Runtime | Docker + Docker Compose |
| Virtualization | Nested virtualization enabled if Docker Desktop / WSL 2 is used |
| Network | Municipality LAN access, inbound HTTPS 443, admin HTTPS 8443, outbound HTTPS 443 |
How we figured these requirements:
- The deployment runs four containers: frontend, backend, PostgreSQL, and pgAdmin.
- Docker Desktop / WSL 2 on a Windows Server VM adds virtualization overhead.
- PostgreSQL needs persistent storage for building data, logs, users, uploaded images, and future growth.
- Building-card exports and GIS snapshots are heavier than normal page views, so 8 GB RAM gives safe headroom.
- The system is for internal municipality users, not high-volume public traffic, so 4 vCPU and 8 GB RAM are enough for the expected workload.
- 100 GB SSD gives room for the repository, Docker images, database volume, pgAdmin volume, logs, uploaded images, generated exports, and growth margin.
A Hebrew customer questionnaire was used to collect the client's final feedback, and the signed response is stored as the customer satisfaction evidence.
Filled response evidence: docs/submissions/stage-b/customer-satisfaction/GhostHouses_Customer_Questionnaire_Response.pdf
Customer-side deployment is tracked in the deployment User Story: Issue #94.
The written communication trail for deployment is documented in email correspondence with the client side, the municipality dev team, municipality IT/security contacts, and the project supervisors CC'd. This evidence covers the deployment requirements, server preparation, security approval process, nested-virtualization discussion, and our attempts to keep the deployment moving professionally.
The Stage B class UML is written in UML 2.5.1 style and rendered with PlantUML.
- Source:
docs/submissions/stage-b/uml/class/class_diagram.puml - Rendered image:
docs/submissions/stage-b/uml/class/class_diagram.png - Vector render:
docs/submissions/stage-b/uml/class/class_diagram.pdf
The diagram shows:
- API layer: controllers, common controller bases, and the separation between authenticated API controllers and simpler controllers.
- Service layer: replaceable contracts for audit, JWT, OTP, and GIS behavior.
- Validation/import layer: shared building and street rules reused by manual editing and Excel import.
- Persistence layer:
AppDbContextas the EF Core boundary for PostgreSQL entities. - Domain layer: the main business entities and relationships used by the system.
The codebase uses practical abstractions only where they reduce coupling or prepare the system for realistic change:
- Template-style controller base:
ApiControllerBaseextends ASP.NETControllerBaseand centralizes shared authenticated API behavior. - Dependency Injection: ASP.NET Core injects services through constructors, so controllers depend on contracts and framework-managed dependencies.
- Interface-based service replacement:
IAuditService,ITokenService,ITwoFactorService, andIGisSnapshotServicehide implementation details behind stable contracts. - Strategy-like integration boundary: GIS snapshot generation is isolated behind
IGisSnapshotService, currently implemented byArcGisSnapshotService. - Adapter boundary for mocked OTP: login depends on
ITwoFactorService, so a real SMS/email provider can be added later without rewriting controller flow. - Centralized validation:
BuildingRulesandStreetRulesare shared by API actions and Excel import logic. - Persistence boundary:
AppDbContextis the single EF Core gateway to PostgreSQL. - High cohesion: controllers handle HTTP, services handle application behavior, rules handle validation, import helpers handle Excel parsing, and models represent business data.
- Low coupling: controllers depend on service interfaces and stable boundaries instead of concrete external systems.
The system is designed to be future proof: likely client, vendor, and deployment changes can be handled by replacing focused parts of the code instead of rewriting the whole application.
- GIS provider changes: the delivered system uses Haifa Municipality ArcGIS because that is the client-approved integration. GIS map and snapshot behavior is isolated behind focused GIS modules and
IGisSnapshotService, with the current backend implementation inArcGisSnapshotService. If the municipality changes GIS endpoints or moves to another provider, most of the replacement work should stay inside the GIS boundary instead of spreading through controllers, exports, or the database model. - OpenStreetMap proof of pivot: a separate proof branch demonstrates that the map provider can be replaced with OpenStreetMap:
feature/map-provider-flexibility/mainandfeature/map-provider-flexibility/#92-openstreetmap-provider-proof. It is intentionally not merged intodevelop,release/*, ormainbecause the client-approved delivery uses Haifa Municipality GIS, but it proves vendor flexibility. - Municipality scalability: GIS-based city mapping is common for municipalities. The system is not hard-coded to Haifa-only UI logic, so another municipality could replace the GIS endpoint/provider and adjust field definitions without a full rewrite.
- OTP provider changes: OTP is mocked for this handoff, but the login flow depends on
ITwoFactorService. A real SMS/email provider can be added later by replacing that service implementation. - Additional external systems: future municipality integrations can follow the same service-contract pattern instead of placing external API logic directly inside controllers.
- Business-rule changes: mandatory fields and validation logic are centralized in
BuildingRulesandStreetRules, so manual editing and Excel import stay consistent when rules change. - Database/schema changes: persistence is concentrated through
AppDbContextand EF Core migrations, so schema evolution happens at the data boundary instead of through scattered SQL. - Frontend/backend separation: the React frontend communicates with the backend through REST APIs, so UI changes and backend persistence changes can evolve separately.
Release checkpoints show continuous project growth:
release/stage-a/sprint-1-mvp: first working MVP / client-demoable version.release/stage-a/sprint-2-final: final Stage A checkpoint.release/stage-b/sprint-1-deployment: deployment-focused Stage B checkpoint.release/stage-b/sprint-2-gis: GIS-focused Stage B checkpoint.release/stage-b/sprint-3-final: intentionally empty for now and will be updated when all remaining issues are closed and the final handoff state is ready.
Open/planned work is tracked through GitHub Issues and the GhostHouses project board.
Current known horizon:
- Real OTP implementation and stronger 2FA enforcement.
- Additional external municipality system integrations beyond GIS, if the municipality provides real API/file contracts.
- Final deployment/handoff completion on the customer server.
- Final customer feedback/questionnaire evidence.
The branch workflow is documented in docs/CONVENTIONS.md.
Current branch model:
mainis reserved for final production/handover history.developis the delivered integration branch.feature/<feature>/maingroups related implementation work.feature/<feature>/#<issue-number>-<slug>is linked to exactly one implementation issue.release/stage-a/...andrelease/stage-b/...branches are release checkpoints fromdevelop.- Normal implementation flow:
develop->feature/<feature>/main->feature/<feature>/#<issue>-<slug>->feature/<feature>/main->develop.
Issue conventions are documented in docs/CONVENTIONS.md.
The repository uses:
- User Story issues with acceptance criteria.
- Non-User-Story implementation issues with
Summary,Scope, andNotes. - Required labels, milestones, project status, parent User Story links, and Development branch links.
- Closing/progress comments with
Time spent:. issue-guard.ymlto comment when issue metadata is missing or inconsistent.
The automated testing workflow is defined in .github/workflows/ci.yml.
It runs on pushes to develop, feature/**, and release/**, on pull requests into develop, and manually through workflow_dispatch.
The CI workflow checks:
- Backend build and tests: restores, builds, and runs
tests/WebServer.Testswith .NET 8 and xUnit. - Frontend build: installs dependencies with
npm ciand runs the Vite production build. - Docker Compose build readiness: validates the Compose configuration with CI-only dummy secrets, then builds the backend and frontend Docker images.
The issue-guard workflow is defined in .github/workflows/issue-guard.yml. It checks GitHub/project-management metadata, while CI checks code and deployment readiness.
This README is structured as both a handoff guide and a Project Delivery reference. It includes:
- Project overview and team information.
- Current capabilities.
- Installation and clean deployment commands.
- Deployment requirements, UML links, dependencies, and hardware sizing.
- Architecture maintainability evidence.
- GitHub workflow evidence.
- CI/test evidence.
- License evidence.
This repository is licensed under the Creative Commons Attribution 4.0 International license (CC-BY-4.0).
Full license text: LICENSE.md.
As part of deployment readiness, the project includes static code analysis, dependency monitoring, and GitHub security controls. These measures improve reviewability and help catch common code, dependency, and secret-handling issues early, but they do not replace a full security code review or an application penetration test on a running system.
Security-readiness evidence is documented in docs/submissions/stage-b/deployment-security/security-readiness.md.
Current repository-side controls include:
- CodeQL static analysis configuration for the C# backend and JavaScript/TypeScript frontend.
- Dependabot configuration for GitHub Actions, NuGet, npm, and Docker base images.
- A vulnerability reporting policy in
SECURITY.md. - Existing CI for backend tests, frontend build, and Docker Compose build readiness.
- Secret handling rules through
.gitignore,project/HANDOFF_SECRETS.md, and local-only.env/ certificate paths.
Controls that still require repository-owner or administrator settings are documented separately: Dependabot alerts/security updates, secret scanning, push protection, branch protection/rulesets, and repository visibility justification.
project/web-server/backend: ASP.NET Core backend.project/web-server/frontend: React frontend.project/docker-compose.yml: top-level Docker Compose deployment.project/db-server: PostgreSQL and pgAdmin compose configuration.docs/: project documentation.docs/submissions/stage-a/: Stage A submission artifacts.docs/submissions/stage-b/: Stage B project delivery artifacts, UML files, and future customer evidence.tests/: automated backend tests..github/workflows/: GitHub Actions workflows.
Maintained by the GhostHouses team.