Nishan
How it works Features Why Nishan Who it's for
Book a demo
← Back to home Trust & Security

Security & Data Handling

Last updated: 30 July 2026. Effective immediately.

On this page

  • 1. Security principles
  • 2. Tenant isolation
  • 3. Encryption
  • 4. Authentication & authorisation
  • 5. API hardening
  • 6. Platform admin controls
  • 7. Audit & monitoring
  • 8. Secure development
  • 9. Backups & recovery
  • 10. Incident response
  • 11. Responsible disclosure
  • 12. Contact

In short: tenant data is isolated at the database level, every request is authenticated, every privileged action is logged, and access keys are hashed. The platform admin layer is a separate identity with a separate signing key and an IP allowlist.

1. Security principles

We design the platform around these principles:

  • Isolation first. A bug in one tenant must not leak data to another tenant. We enforce this at the database, not just the application layer.
  • Least privilege. The platform admin layer can read across tenants by design, but every cross-tenant read is recorded.
  • Defence in depth. TLS, hashed credentials, signed tokens, row-level security, audit logs, rate limits, and IP allowlists all work together.
  • Reversibility. Every state change (plan edit, suspension, password reset, impersonation) is reversible and recorded.
  • No secrets in code. All secrets live in environment variables. The repository has no production credentials.

2. Tenant isolation

Nishan runs on PostgreSQL with PostGIS. Every operational table includes a tenant_id column and is protected by a row-level security (RLS) policy. The application connects as a role that has RLS enforced; the only way to read across tenants is to connect as a separate role that bypasses RLS, which is reserved for the platform admin layer and is itself audited.

Tests prove isolation: 22 backend tests are dedicated to cross-tenant leakage scenarios, inside a suite of 372 that must pass before any release.

3. Encryption

  • In transit: TLS 1.2+ on all public endpoints. HTTP requests are redirected to HTTPS.
  • At rest: managed disk encryption on database and object storage volumes.
  • Passwords: argon2id with parameters tuned for current hardware. Stored as a self-describing PHC string.
  • API keys: SHA-256 hash stored; raw key is shown once at creation or rotation.
  • Refresh tokens: SHA-256 hash stored in the platform_admin_refresh_tokens table.
  • JWT signing: HS256 with a 32+ byte secret. Separate secrets for tenant and platform-admin tokens.

4. Authentication & authorisation

  • Tenant users authenticate with email + password (argon2id) and receive a 15-minute access token, plus a refresh cookie (httpOnly, SameSite=Strict, Secure in production). A dashboard session ends after 60 minutes of inactivity, and cannot run longer than 7 days in total no matter how actively it is used.
  • API access uses a per-tenant API key passed in the Authorization: Bearer header.
  • Roles: owner, admin, dispatcher, viewer. Each role has explicit allow / deny lists for every endpoint.
  • Platform admins authenticate on a separate /admin/auth/login route with a separate JWT secret. The JWT carries type: 'platform_admin' and the platform-admin middleware rejects any token that does not.
  • Failed logins are rate-limited per IP (10 per minute) and also counted against the account itself: 8 failures lock a tenant user for 15 minutes, 5 failures lock a platform admin for 30 minutes. While an account is locked, even the correct password is refused.

5. API hardening

  • HTTPS-only; HTTP requests get a 301 to HTTPS.
  • Strict Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy headers on every response.
  • Request bodies are size-limited (default 1 MB) and parsed with strict Zod schemas; unknown fields are rejected.
  • All input strings are normalised, length-capped, and (for free-text fields) HTML-escaped before logging.
  • Rate limits are enforced per client IP: 600 requests per minute on the API, 30 on public capture endpoints, 10 on login. Per-API-key limits are not yet in place.
  • Geocoder calls go through a provider router that includes a circuit breaker and cost cap per provider.

6. Platform admin controls

  • Separate platform_admins table, separate JWT secret (ADMIN_JWT_SECRET), separate refresh-token table.
  • Refresh cookie is path-scoped to /admin, httpOnly, SameSite=Strict.
  • Platform-admin sessions use a 5-minute access token, end after 15 minutes of inactivity, and cannot exceed 12 hours in total.
  • Impersonation tokens are capped at 10 minutes regardless of the tenant JWT TTL.
  • Owner password reset returns a one-time password in the response and rotates all active refresh tokens for the affected tenant.
  • Every cross-tenant read or write is recorded in platform_admin_audit with actor, action, target, IP and user agent.

7. Audit & monitoring

  • Append-only audit log per tenant for owner / admin / dispatcher actions, plus a separate platform_admin_audit for the admin layer.
  • Server access logs retained 30 days. Logs are redacted of PII (phone, email, full name, key material) at write time.
  • Health endpoints, request counters, and provider-cost metrics exported for monitoring.
  • Anomalous patterns (sudden spikes in failed logins, geocoder cost overruns, repeated cross-tenant denied reads) raise alerts.

8. Secure development

  • Changes are code-reviewed, and the full test suite (372 tests) must pass before release.
  • Type checking runs on every build and dependency audits are run before each release.
  • Secrets are loaded from environment variables; the repo is scanned for accidental secret commits.
  • Database migrations are versioned, reviewed, and reversible.

9. Backups & recovery

  • Database: nightly compressed dumps with 14-day retention. The restore procedure has been tested.
  • Door photos: held on encrypted server disk, deleted when the customer or tenant is erased, with a weekly sweep that removes any orphaned file.
  • Recovery time objective (RTO): 4 hours. Recovery point objective (RPO): 24 hours.
  • Backups currently sit on the database host. Off-host copies are being added.

10. Incident response

  • Confirmed security incidents are notified to affected tenant owners within 72 hours of detection, in line with applicable data-protection requirements.
  • Notifications include what we know, what we are doing, and what you can do.
  • Post-incident reports summarise root cause and remediation, and are available to affected tenants on request.

11. Responsible disclosure

If you have found a security issue, please email Support@doro.pk with a description and reproduction steps. We will acknowledge within one business day and work with you on coordinated disclosure. We do not pursue legal action against good-faith security research.

12. Contact

Security: Support@doro.pk
Privacy: Support@doro.pk
General: Support@doro.pk

Nishan Mapping API

Verified-location memory for delivery teams. Pakistan-first.

Product

How it works Features Why Nishan Who it's for

Company

Contact Security

Legal

Privacy Terms Cookies

© Nishan. All rights reserved.

Built for delivery teams who are tired of paying to find the same doors.