ArkanPM treats security and audit as platform foundations, not add-ons. This reference covers how authentication, authorization, sessions, audit logging, and data retention work — useful for admins, compliance teams, and anyone evaluating the platform.
Authentication
Password-based sign-in
- Email + password is the default sign-in method.
- Passwords must meet the tenant's policy (default: 10+ characters, mixed case, numbers; admins can tighten).
- Passwords are hashed server-side with bcrypt. Never stored in plain text.
Multi-factor authentication (MFA)
- TOTP (Time-based One-Time Password) — compatible with Google Authenticator, Authy, Microsoft Authenticator, 1Password, and other standard authenticators.
- QR code provisioning — scan the QR code during setup, your authenticator adds the account.
- Backup codes — 8 single-use codes issued at setup for recovery if your device is lost.
- Enforcement levels:
- Off (not enforced)
- Required for admins only
- Required for all users
- Required per role (custom)
Admins set enforcement at Sidebar > Admin > Settings > Security > MFA.
Account lockout
- 5 failed password attempts within a short window → account locked for 15 minutes.
- Admins can unlock early at
Users > [user] > Unlock Account. - Users are notified of lockouts by email so they're aware of potential credential-stuffing attempts.
Session tokens
- Access tokens — 15-minute TTL. Carried on every API request.
- Refresh tokens — 7-day TTL. Used to quietly issue new access tokens.
- Idle timeout — sessions idle beyond the refresh window require re-sign-in.
- Concurrent session limit — admins cap how many active sessions a single user can have.
Authorization
Role-based access control (RBAC)
Every action in ArkanPM is gated by a permission. Permissions are grouped into roles. Users are assigned one or more roles. When a user attempts an action, the platform checks whether any of their roles grants that permission.
11 built-in roles, each with pre-defined permission sets. Custom roles are built in Admin > Roles > Create Role by selecting permissions from the matrix.
Attribute-based access control (ABAC)
RBAC alone is coarse-grained. ABAC adds context-aware rules on top:
- Scope attributes — a user is scoped to specific buildings, floors, or units. Even if their role grants
work_order.view, they only see WOs within their scope. - Temporal scope — scopes can have a start and end date, so contractor access auto-expires.
- Financial masking attributes — certain roles/attributes mask financial fields (cost, rent, invoice totals) at the API layer, so the data never reaches the browser.
ABAC is enforced server-side. You cannot bypass it by manipulating the browser.
Tenant isolation — PostgreSQL Row-Level Security (RLS)
The strongest layer of isolation is at the database itself. Every table that holds tenant data is protected by a Row-Level Security policy. Every query automatically filters by tenant_id = <current tenant>, enforced by PostgreSQL — not the application code.
This means: even if a bug in application code tried to return data from another tenant, the database would refuse. Multi-tenant isolation is architectural, not advisory.
Tenant status guards
- Active — tenant operates normally.
- Suspended — all users at that tenant are locked out at the authentication layer, regardless of individual permissions. Data is preserved.
- Terminated — tenant is marked for archival/deletion per retention policy.
Status guards run at every authentication attempt; a suspended tenant's users cannot sign in at all.
Audit trail
What's logged
Every create, update, delete, login, logout, sign-in failure, MFA event, password change, and role change is logged.
Each audit entry has:
- Actor — which user performed the action
- Action — the verb (create / update / delete / sign_in / sign_out / etc.)
- Entity type — which module the record belongs to (work_order, lease, user, etc.)
- Entity ID — which specific record
- Old values — JSON snapshot of the record before the change (for updates and deletes)
- New values — JSON snapshot after the change
- Timestamp — ISO 8601 with milliseconds
- IP address — source IP
- User agent — browser/device string
Where to see it
Sidebar > Admin > Audit Logs. Filter by:
- User (actor)
- Entity type
- Action
- Date range
- Free-text search across old/new JSON
Click any row to see the full diff — old values and new values side-by-side.
Point-in-time reconstruction
For any record, you can reconstruct its state at any prior moment by replaying the audit log forward from creation. ArkanPM support uses this for investigations and recovery scenarios.
Soft deletes
When a record is "deleted" in the UI, it's marked with a deleted_at timestamp and hidden from default queries — not physically removed. The audit entry is preserved regardless.
Retention policy determines when soft-deleted records are eventually purged. Support can undelete a soft-deleted record before purge if needed.
Data retention
Admin > Settings > Data Retention controls how long different data categories are kept.
Per-category policies
| Category | Default retention |
|---|---|
| Work orders, inspections | 7 years |
| Leases, move-in/out records | 10 years |
| Documents — compliance category | 10 years |
| Documents — financial category | 7 years |
| Documents — operational category | 3 years |
| Documents — temporary category | 90 days |
| Audit logs | 7 years |
| Soft-deleted records | 30 days before purge |
| Notification logs | 90 days |
| Integration call logs | 90 days (configurable) |
These defaults match common GCC regulatory expectations. Tune them to your specific compliance regime.
Archival
Records past retention are moved to cold storage — still recoverable via support request but not indexed for normal queries. After the archive window passes, they're purged per policy.
Export before purge
Before lowering a retention window, use Admin > Data Retention > Export to snapshot data that would be affected. Exports are JSON bundles with full fidelity.
Secrets and credentials
API keys
- Generated per tenant, per purpose (e.g., one key for your ERP integration, another for internal scripts).
- Each key has a human-readable name, an owner, and a permission scope (custom role).
- Keys are shown once at creation. Store them securely — they can't be re-viewed.
- Keys can be rotated (issue a new one, revoke the old) without downtime if you plan overlap.
- Keys can be revoked immediately for incident response.
Webhook signing secrets
- Every outbound webhook carries a shared secret.
- Secrets are rotatable per webhook.
- Old secret remains valid for a grace period (default 24 hours) after rotation so your receiver has time to pick up the new one.
Integration credentials
Stored encrypted at rest. Visible to admins only in masked form in the UI. Changeable without downtime by updating the integration config.
Transport security
- All API and web traffic is HTTPS only.
- HSTS header enforces HTTPS on modern browsers.
- Helmet security headers set on every response:
Content-Security-PolicyX-Frame-Options: DENYReferrer-PolicyPermissions-Policy
- Weak TLS versions and ciphers are disabled.
Data masking by role
ABAC rules can mask individual fields. Common masking patterns:
- Building Manager — sees occupancy but not rent amounts
- Maintenance Technician — sees work orders but not WO cost fields
- Owner — sees monthly income but not individual unit expenses
- Resident — sees their own data only
Masking happens at the API layer. The masked fields are replaced with null (or redacted marker) before the response leaves the server. Browsers and integrations can't reach the masked data regardless of client behavior.
Incident response quick reference
You suspect a compromised user account
Users > [user] > Force Sign-Out From All Sessions.Users > [user] > Reset Password(sends a reset link).Users > [user] > View Activity— review recent actions in the audit log.- Rotate any API keys that user created or accessed.
- If damage was done, use the audit log's point-in-time reconstruction to identify affected records and recover them.
You suspect a compromised API key
Admin > Settings > API Keys > [key] > Revoke. Immediate effect.- Review the audit log filtered by "actor: api-key-name" for recent activity.
- Rotate any integrations depending on that key.
You suspect a compromised webhook secret
Admin > Settings > Webhooks > [webhook] > Rotate Secret.- Update your receiver with the new secret before the grace period expires.
You suspect tenant-wide compromise
Admin > Tenants > [tenant] > Suspend(locks all users out immediately).- Contact ArkanPM support.
- Use the audit log to understand the blast radius.
- Rotate every credential before resuming.
Compliance posture summary
- Multi-tenancy: PostgreSQL RLS at the database layer.
- Authentication: bcrypt password hashing, TOTP MFA, 8 backup codes, 5-attempt lockout, 15/7-day session lifecycle.
- Authorization: RBAC + ABAC with financial masking, 11 built-in roles.
- Audit: full JSON-diff audit trail, point-in-time recovery, 7-year default retention.
- Transport: HTTPS only, HSTS, Helmet security headers.
- Regional: configurable data residency and locale (AED/SAR/QAR/USD, en/ar).
For a procurement-grade security briefing with architecture diagrams and certifications, ask your ArkanPM account team.
Related:
- Admin Handbook → — configuring the above
- Integrations Reference → — API keys, webhook signatures