Skip to content

rcadavos/security-agency

Repository files navigation

Bantay — Security Agency Management (Philippines)

Compliance-first SaaS for Philippine private-security agencies. The wedge — and the current MVP slice — is the license & certification expiry tracker: guards operating on expired LISG/NBI/clearances expose agencies to PNP sanctions and lost contracts, so the system flags every credential at 30 / 7 / 1 days before it lapses.

Working product name: Bantay (Filipino: to guard / watch over).

Stack

Layer Choice
Framework Next.js 16 (App Router) · React 19 · TypeScript
UI Tailwind v4 + shadcn/ui (Base UI primitives)
Design Notion-inspired tokens — see DESIGN.md
Backend Supabase — Postgres + Auth + data via @supabase/supabase-js (PostgREST), no ORM
Auth Supabase Auth (email + password, cookie sessions via @supabase/ssr)
Tenant isolation Postgres Row Level Security + app-level requireAgency() scoping
Validation Zod

Getting started

  1. Install

    pnpm install
  2. Create a Supabase project, then copy .env.example.env.local and set NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY (Settings → API). For local dev without SMTP, disable Authentication → Email → Confirm email.

  3. Apply the schema — run the migrations in order in the Supabase SQL editor (or supabase db push):

    1. 0001_init.sql — tables, indexes, RLS.
    2. 0002_profiles_roles_provisioning.sqlprofiles, roles, is_superadmin(), the handle_new_user signup trigger (provisions profile + agency), superadmin RLS bypass, and backfills.
    3. 0003_promote_superadmin.sql — promotes the platform owner to superadmin.

    Roles: platform_role is user | superadmin. The superadmin allowlist email is hardcoded in 0002/0003 (currently rgcadavos@gmail.com) — change it there if needed. Break-glass (promote any user as the service role / SQL editor): update public.profiles set role='superadmin' where id = (select id from auth.users where lower(email)=lower('<owner>'));

  4. Run

    pnpm dev

    Sign up, then add guards and their credentials. To preview the dashboard with sample data, set SUPABASE_SERVICE_ROLE_KEY and SEED_OWNER_USER_ID (your Supabase user id) in .env.local and run pnpm db:seed.

Scripts

Script Purpose
pnpm dev / build / start Next.js dev / production build / serve
pnpm lint / pnpm typecheck ESLint / tsc --noEmit
pnpm db:seed Seed demo guards + credentials (uses the service-role key)

Architecture notes

  • Multi-tenancy. Every row carries an agency_id. For the MVP an agency maps to its owner (agencies.owner_user_id = Supabase user id). Isolation is enforced twice: RLS policies in the DB, and requireAgency() (src/lib/auth.ts) scoping inside every Server Action and query.
  • Data access. @supabase/supabase-js (PostgREST). PostgREST returns snake_case; src/lib/queries.ts maps rows to the camelCase domain types the UI uses. Enum tuples live in src/lib/constants.ts, row types in src/lib/db-types.ts.
  • proxy.ts (Next 16's renamed middleware) does Supabase session refresh and emits the per-request strict CSP nonce.
  • Compliance logic lives in src/lib/compliance.ts — the 30/7/1-day status ramp and labels.
  • See SECURITY.md for the hardening checklist and the securityheaders.com target.

Roadmap (post-MVP)

Duty Detail Orders (per-client + internal) · timesheet → DOLE payroll prep · per-client SOA billing (PDF) · incident logging · guard mobile app with geofenced GPS check-in · SMS (Twilio) alerts.

About

Run your security agency with confidence. Manage guards, clients, shifts, patrols, reports, payroll, and operations from a single cloud-based platform designed for modern security companies.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors