Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
639e922
1 donor ≠ 5 units
aashir-athar Apr 14, 2026
522b58b
Switched to .maybeSingle(), which returns null for a missing row inst…
aashir-athar Apr 15, 2026
728d63b
debugging
aashir-athar Apr 15, 2026
d13aca7
Create README.md
aashir-athar Apr 15, 2026
e5325ae
chore: baseline WIP before production hardening pass
aashir-athar May 12, 2026
a6258aa
hardening: full production pass + Vercel + real-time chat
aashir-athar May 12, 2026
20f68ad
merge: origin/master into hardening branch + drop /debug-env
aashir-athar May 12, 2026
b62c155
Merge pull request #1 from aashir-athar/production-hardening-2026-05-12
aashir-athar May 12, 2026
5889d90
fix(vercel): drop crons from vercel.json (Hobby = daily only)
aashir-athar May 12, 2026
b75734e
feat(2026-ui): full redesign + RLS grants fix + debug-surfaceable errors
aashir-athar May 12, 2026
0f339a1
Merge pull request #2 from aashir-athar/feat/2026-ui-overhaul-2026-05-12
aashir-athar May 12, 2026
1030ef7
feat(uber-sweep): Request-screen design language across every surface
aashir-athar May 12, 2026
cd31d75
Merge pull request #3 from aashir-athar/feat/uber-sweep-2026-05-12
aashir-athar May 12, 2026
556df86
fix(hardening): TOCTOU, race, typed routes, schema invariants — revie…
aashir-athar May 12, 2026
ad44f79
Merge pull request #4 from aashir-athar/fix/hardening-pass-2026-05-14
aashir-athar May 12, 2026
9444c83
fix(backend): PATCH /profiles/me accepts null address (was rejecting …
aashir-athar May 12, 2026
8fd2e89
Merge pull request #5 from aashir-athar/fix/address-validator-nullabl…
aashir-athar May 12, 2026
437a121
fix: contact-channel closure on request seal + donor age window 18-65…
aashir-athar May 12, 2026
9a45f92
Merge pull request #6 from aashir-athar/fix/contact-closure-and-age-r…
aashir-athar May 12, 2026
c17becb
feat(maps): swap Google-Maps-dependent react-native-maps for free Map…
aashir-athar May 15, 2026
a718225
fix(backend): security + correctness hardening, Express 5, deps to la…
aashir-athar Jun 16, 2026
b874d31
chore(mobile): upgrade Expo SDK 54 -> 56 (RN 0.85, React 19.2, TS 6)
aashir-athar Jun 16, 2026
b8234bd
feat(mobile): Phase C new-stack foundation (Tamagui + Zustand + Query…
aashir-athar Jun 16, 2026
920b113
fix(theme): WCAG 2.2 AA contrast in light theme
aashir-athar Jun 16, 2026
2f177f4
refactor(mobile): move source under src/ per SDK 56 layout
aashir-athar Jun 16, 2026
1f0a090
feat(ui): composite design-system components
aashir-athar Jun 16, 2026
a596b38
feat(mobile): NativeTabs navigation + activate new stores (transition…
aashir-athar Jun 16, 2026
18536e4
feat(auth): rebuild sign-in/OTP screen on the new stack
aashir-athar Jun 16, 2026
7305ff5
feat(ui): data composites (RequestCard, ProfileCard, UrgencyBanner, S…
aashir-athar Jun 16, 2026
ff5de6d
feat(screens): rebuild my-requests + history on the new stack
aashir-athar Jun 16, 2026
2ca3e03
feat(screens): rebuild profile (account) on the new stack
aashir-athar Jun 16, 2026
5df2161
feat(screens): rebuild Find (donors) tab + port useLocation
aashir-athar Jun 16, 2026
0d8774f
feat(screens): rebuild donor home on the new stack
aashir-athar Jun 16, 2026
7c62b9c
feat(chat): rebuild realtime chat on the new stack
aashir-athar Jun 17, 2026
1015e98
feat(map): live tracking map + persistent background donor heartbeat
aashir-athar Jun 17, 2026
46690d9
feat(app): rebuild onboarding, post-request, request/donor detail, ed…
aashir-athar Jun 17, 2026
bae4dd0
refactor(mobile): drop the legacy context+component layer, wire push …
aashir-athar Jun 17, 2026
7e2bc1c
chore: repo tooling — line-ending normalization, Prettier, Node pin
aashir-athar Jun 17, 2026
09bb86e
test: unit suites for the rules that must never drift
aashir-athar Jun 17, 2026
e04ad84
ci: GitHub Actions for mobile, backend, schema, and EAS
aashir-athar Jun 17, 2026
36df624
chore: husky pre-commit guard for the house rules
aashir-athar Jun 17, 2026
211cf8f
style: purge em/en dashes and emoji repo-wide
aashir-athar Jun 17, 2026
74cf3c7
docs: remove REDESIGN_PLAN.md
aashir-athar Jun 17, 2026
5295b00
docs: refresh README for the new stack + add zero-to-deploy guide
aashir-athar Jun 17, 2026
194b68e
feat(reputation): donor reputation tiers + verified-badge program
aashir-athar Jun 17, 2026
8cae223
chore: worklets babel plugin, track env templates, drop Google Maps r…
aashir-athar Jun 17, 2026
853a681
a11y(toast): add role + label to the toast action button
aashir-athar Jun 17, 2026
a023c95
fix: address code-review + security findings on the live-location flow
aashir-athar Jun 17, 2026
ccf4a73
docs(hardening): record Phase F security review + owner action items
aashir-athar Jun 17, 2026
49ec737
chore(mobile): npm audit fix - clear the critical + several high advi…
aashir-athar Jun 17, 2026
4b518c2
style: finish the em-dash/emoji purge (SQL, migrations, scripts)
aashir-athar Jun 17, 2026
1d1bfc6
feat(web): scaffold Next.js site + landing, EAS production workflow
aashir-athar Jun 17, 2026
b355cab
feat(web): functional foundation - lib, auth, providers, UI kit, sign…
aashir-athar Jun 17, 2026
a88426b
feat(web): full app functionality - all screens, maps, realtime chat
aashir-athar Jun 17, 2026
313632c
fix(mobile): bump expo-persistent-background-location 0.1.1 -> 0.1.2
aashir-athar Jun 17, 2026
5c76633
feat(web): branded error/404/loading states, drop scaffold assets
aashir-athar Jun 17, 2026
0b35e61
feat(web): edit-profile screen (role, contact, blood group, medical, …
aashir-athar Jun 17, 2026
0f7e71f
feat(web): static export for GitHub Pages + deploy workflow
aashir-athar Jun 17, 2026
ab3ee9b
docs(web): proper web README (setup, build, GitHub Pages) + root stru…
aashir-athar Jun 17, 2026
1331c1c
fix(web): landing CTA reads 'Use the app' not 'Get the app'
aashir-athar Jun 17, 2026
2760e49
fix(mobile): bump expo-persistent-background-location 0.1.2 -> 0.1.3
aashir-athar Jun 17, 2026
5713624
merge: reconcile origin/master into the production rebuild
aashir-athar Jun 17, 2026
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
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[*.{png,jpg,jpeg,gif,webp,ttf,otf,woff,woff2,ico,hbc}]
trim_trailing_whitespace = false
insert_final_newline = false
28 changes: 28 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Normalize line endings: store as LF in the repo, check out native on each OS.
# This kills the "LF will be replaced by CRLF" churn while keeping Windows happy.
* text=auto

# Source and config are always LF.
*.ts text eol=lf
*.tsx text eol=lf
*.js text eol=lf
*.jsx text eol=lf
*.json text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.sql text eol=lf
*.sh text eol=lf

# Binary assets — never touch their bytes.
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.webp binary
*.ttf binary
*.otf binary
*.woff binary
*.woff2 binary
*.ico binary
*.hbc binary
53 changes: 53 additions & 0 deletions .github/ci/supabase-test-prelude.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
-- CI-only Supabase compatibility shims.
-- supabase_schema.sql targets a Supabase database, which ships an `auth` schema,
-- an `auth.uid()` function, the anon/authenticated/service_role roles, and the
-- `supabase_realtime` publication out of the box. A vanilla Postgres service has
-- none of those, so we create the minimum surface the schema references before
-- applying it. This proves the DDL, RLS policies, grants, triggers, and indexes
-- all apply cleanly - it is not a runtime auth emulation.

create extension if not exists "uuid-ossp";
create extension if not exists "pgcrypto";

-- auth schema + the slice of auth.users our trigger reads (id, email).
create schema if not exists auth;

create table if not exists auth.users (
id uuid primary key default gen_random_uuid(),
email text,
raw_user_meta_data jsonb default '{}'::jsonb,
created_at timestamptz default now()
);

-- auth.uid() - the only auth.* function the policies call. Resolves from a JWT
-- claim GUC when present, else null (no rows visible), matching Supabase.
create or replace function auth.uid()
returns uuid
language sql
stable
as $$
select nullif(current_setting('request.jwt.claim.sub', true), '')::uuid
$$;

-- Roles referenced by GRANT and `to <role>` policy clauses.
do $$
begin
if not exists (select 1 from pg_roles where rolname = 'anon') then
create role anon nologin noinherit;
end if;
if not exists (select 1 from pg_roles where rolname = 'authenticated') then
create role authenticated nologin noinherit;
end if;
if not exists (select 1 from pg_roles where rolname = 'service_role') then
create role service_role nologin noinherit bypassrls;
end if;
end $$;

-- The realtime block in the schema ALTERs this publication to add tables, so it
-- must already exist (Supabase pre-creates it).
do $$
begin
if not exists (select 1 from pg_publication where pubname = 'supabase_realtime') then
create publication supabase_realtime;
end if;
end $$;
51 changes: 51 additions & 0 deletions .github/workflows/backend-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: backend-ci

# Lint + unit/integration tests for the Express API. The health test boots the
# full middleware stack via supertest (no port bind, expo-server-sdk stubbed),
# so this also catches a broken route table or a bad require.

on:
push:
branches: [master]
paths:
- 'backend/**'
- '.github/workflows/backend-ci.yml'
pull_request:
paths:
- 'backend/**'
- '.github/workflows/backend-ci.yml'
workflow_dispatch:

concurrency:
group: backend-ci-${{ github.ref }}
cancel-in-progress: true

jobs:
verify:
runs-on: ubuntu-latest
defaults:
run:
working-directory: backend
env:
# Dummy credentials so the admin client init does not process.exit(1).
# No test reaches Supabase; /health and the geo units never connect.
SUPABASE_URL: http://localhost:54321
SUPABASE_SERVICE_ROLE_KEY: ci-test-service-role-key
NODE_ENV: test
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version-file: backend/.nvmrc
cache: npm
cache-dependency-path: backend/package-lock.json

- name: Install dependencies
run: npm ci

- name: Lint
run: npm run lint

- name: Tests
run: npm run test:ci
68 changes: 68 additions & 0 deletions .github/workflows/deploy-web-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: deploy-web-pages

# Builds the web/ app as a static export and publishes it to GitHub Pages.
# Set these repository secrets first (Settings -> Secrets and variables -> Actions):
# NEXT_PUBLIC_API_URL, NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY
# And enable Pages with "GitHub Actions" as the source (Settings -> Pages).

on:
push:
branches: [master]
paths:
- 'web/**'
- '.github/workflows/deploy-web-pages.yml'
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: web
env:
# Project Pages serve under https://<user>.github.io/<repo>, so the app
# needs basePath /BludStack. For a custom domain or a <user>.github.io repo,
# set this to an empty string.
NEXT_PUBLIC_BASE_PATH: /BludStack
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: web/package-lock.json

- name: Install dependencies
run: npm ci

- name: Build static export
run: npm run build

- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: web/out

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
61 changes: 61 additions & 0 deletions .github/workflows/eas-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: eas-build

# Owner-triggered cloud build. Runs on a version tag (v1.2.3) or manual dispatch.
# Requires the EXPO_TOKEN repository secret (Expo access token). This does not run
# on every push - device builds cost money and minutes.

on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
platform:
description: Platform to build
type: choice
default: all
options: [all, android, ios]
profile:
description: EAS build profile
type: choice
default: production
options: [production, preview, development]

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: mobile
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version-file: mobile/.nvmrc
cache: npm
cache-dependency-path: mobile/package-lock.json

- name: Setup EAS
uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}

- name: Install dependencies
run: npm ci

- name: Guard EXPO_TOKEN
run: |
if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then
echo "::error::EXPO_TOKEN secret is not set. Add it in repo Settings -> Secrets -> Actions."
exit 1
fi

- name: EAS build
run: |
eas build \
--non-interactive \
--no-wait \
--platform "${{ github.event.inputs.platform || 'all' }}" \
--profile "${{ github.event.inputs.profile || 'production' }}"
54 changes: 54 additions & 0 deletions .github/workflows/mobile-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: mobile-ci

# Static verification for the Expo app: install, typecheck, lint, unit tests,
# Expo health, and a Metro bundle. No device build here - that lives in
# eas-build.yml and is owner-triggered.

on:
push:
branches: [master]
paths:
- 'mobile/**'
- '.github/workflows/mobile-ci.yml'
pull_request:
paths:
- 'mobile/**'
- '.github/workflows/mobile-ci.yml'
workflow_dispatch:

concurrency:
group: mobile-ci-${{ github.ref }}
cancel-in-progress: true

jobs:
verify:
runs-on: ubuntu-latest
defaults:
run:
working-directory: mobile
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version-file: mobile/.nvmrc
cache: npm
cache-dependency-path: mobile/package-lock.json

- name: Install dependencies
run: npm ci

- name: Typecheck
run: npm run typecheck

- name: Lint
run: npm run lint

- name: Unit tests
run: npm run test:ci

- name: Expo Doctor
run: npx expo-doctor

- name: Metro export (Android)
run: npx expo export --platform android --output-dir dist
Loading
Loading