Inspiration

The intention behind our project was for us to create something that was able to help students whilst also being intentional about not collecting user data.

What it does

A Python-based tool that helps users find safer walking/biking routes and accessible transit options without ever collecting their location history, identity, or personal data.

How we built it

We built SafePath in Python as three clean layers so each part could be tested on its own.

Presentation: Streamlit and Folium. An interactive map, a query box, a safety breakdown panel, and a cost comparison.

Logic: Pure Python. We score every street segment from OpenStreetMap tags — lighting, wheelchair access, incline, and path type — then find the safest weighted path using NetworkX. A simple rule-based parser turns plain-language queries like "safe route to the library, avoid steep hills" into scoring preferences.

Data: A locally cached OpenStreetMap graph, a static fare table, and an in-memory session. Nothing is written to disk.

We wrote the privacy contract first, before the app existed. privacy.py defines a strict whitelist of allowed session fields and a blacklist of forbidden ones (names, emails, user IDs, IPs, history, timestamps). Then we wrote seven tests in tests/test_privacy.py that prove the claims — including one that monkeypatches Python's socket library to raise if any routing code tries to open a network connection.

We also prototyped homomorphic encryption in he_oracle.py so an untrusted scoring server could compute a route's safety score on encrypted data without ever seeing the route.

Stack: Python, Streamlit, Folium, OSMnx, NetworkX, lightphe, pytest. 30 passing tests.

Challenges we ran into

The cached graph problem. OSMnx downloads map data from the network at runtime. That would break our "no network calls" claim. We solved it by caching graph.graphml at setup time and committing it to the repo, so the whole app runs offline.

Merging from a fork. One teammate worked from a fork with divergent history, and the merge would have conflicted on a 250,000-line graph file. We merged selectively — checking out only the files we didn't already have — instead of doing a full merge.

Test-first privacy. Writing the privacy tests before the routing code meant one test sat as SKIPPED for hours, waiting for routing to exist. When the routing landed and that test turned green, it was the first real proof that our privacy claims held up under actual routing.

Keeping the scope honest. It's tempting to claim more than we built. We were deliberate about what we could prove — for example, our homomorphic encryption prototype scores routes on ciphertext, but it does not route on ciphertext. We say so explicitly in the code and in our pitch.

Accomplishments that we're proud of

30 passing tests, including a live proof that routing makes zero network calls. Our privacy claim isn't a slide — it's executable. Anyone can run pytest or python demo/privacy_proof.py and watch three checks pass: no files written, no sockets opened, no PII in the schema.

Privacy by design, not by promise. We wrote the privacy contract first and built the app to pass it. That shaped every decision after — what we stored, what we computed, what we refused to collect.

Explainable scoring. A user can see exactly why a route scored the way it did — the lighting percentage, the steep segments, the missing curb ramps, and the weights behind the number. No black box.

A homomorphic encryption prototype. A genuine cryptographic guarantee, not a feature slide. The server computes a score on encrypted data. Even we can't see what we're scoring.

What we learned

Privacy is a design pattern, not a feature. Writing the privacy contract first changed the shape of everything else. Once you decide what you'll never collect, the architecture gets simpler, not harder.

Verifiable beats defensible. "We promise not to sell your data" is a claim. "Run this test and watch it pass" is proof. The second one is much harder to argue with.

Testing early pays off late. One of our privacy tests sat skipped for hours waiting on a teammate's code. When his routing landed, that test immediately proved something we couldn't have proven any other way.

Honest scoping wins. We had three hours of work and sixteen hours of time. Being clear about what we could finish well — instead of trying to finish everything — is why we have a working app with tests, not a broken one with half-features.

What's next for safePath

Expand the scoring model. More OpenStreetMap tags: crosswalks, tactile paving, benches, shade, curb heights. The more tags we read, the better the safety picture.

Crowd-sourced reports without a server. Federated learning would let users contribute accessibility reports — "this curb is broken," "this light is out" — without a central server logging who reported what.

Production-grade homomorphic scoring. Our prototype uses Paillier, which is slow. A scheme with better performance characteristics would make encrypted scoring practical at scale.

Partnerships. Municipalities and universities running accessibility and safe-routes programs are the natural partners. The privacy architecture is a selling point, not a limitation, for public-sector use.

Built With

  • folium
  • lightphe
  • networkx
  • osmnx
  • pytest
  • python
  • streamlit
Share this project:

Updates

Submission history