Skip to main content

Data dictionary

This dictionary lists the key tables of the app database and the control database (about 140, many grouped into shared sections). Table names are aligned with the module specs in the Modules section. The conventions behind every table are in the data model overview, and the relationships are drawn in the ERD.

How to read it:

  • Standard columns are not repeated. Unless a table says otherwise, it also has id uuid PK (UUIDv7), tenant_id uuid NOT NULL, UNIQUE (tenant_id, id), created_at, created_by, updated_at, updated_by and row_version. Append-only tables (marked append-only) have no updated_* or row_version.
  • FK means a composite foreign key (tenant_id, column) to the named table. Soft ref means a UUID reference without a constraint (used when the target is downstream in the module DAG or partitioned).
  • Class is the data classification (C0–C4) for the sensitive columns only; unmarked columns are C1 or C2.
  • Money columns are bigint paise. Days are numeric(6,2). Rates are numeric(9,4).
  • Enumerated values are text + CHECK. Values are listed in the Notes column.

Kernel (sys_)​

sys_tenant​

The cell-local copy of the tenant record, written only by the provisioning job from the control plane.

ColumnTypeConstraintsNotes
iduuidPKSame ID as tenant.id in the control plane. This table has no tenant_id column; RLS uses id.
slugtextUNIQUE, NOT NULLImmutable
nametextNOT NULLDisplay name
statustextCHECKTRIAL, ACTIVE, PAST_DUE, SUSPENDED, CHURNED, DELETED (mirrors the control plane)
plan_codetextNOT NULLCached for diagnostics; entitlements are checked through the SDK
timezonetextNOT NULL, default Asia/KolkataIANA name
settingsjsonbLocale, date format, financial-year start

sys_outbox_event​

Append-only, partitioned weekly by occurred_at.

ColumnTypeConstraintsNotes
iduuidPK with occurred_atAlso the CloudEvents id
event_typetextNOT NULL<module>.<entity>.<past-tense-verb>
schema_versionintNOT NULLPayload schema version
aggregate_typetextNOT NULLFor example lve_request
aggregate_iduuidNOT NULL
aggregate_versionintFor order-sensitive consumers
payloadjsonbNOT NULLC0–C2 only
actorjsonbUser, system or API client; on-behalf flag
trace_contexttextW3C traceparent
occurred_attimestamptzNOT NULLPartition key
published_attimestamptzNull until relayed; partial index WHERE published_at IS NULL

sys_inbox_receipt​

Append-only. Consumer-side deduplication.

ColumnTypeConstraintsNotes
subscribertextPK (with event_id)Handler name, for example att.leave-mark
event_iduuidPK
processed_attimestamptzNOT NULLPurged after 14 days

sys_audit_event​

Append-only, partitioned monthly by occurred_at; the app role has INSERT and SELECT only.

ColumnTypeConstraintsNotes
actor_typetextCHECKUSER, API_CLIENT, SYSTEM, PLATFORM_SUPPORT, KIOSK
actor_user_iduuid
on_behalf_of_user_iduuid
support_grant_iduuidSoft refControl-plane grant when platform staff act
actiontextNOT NULLPermission key or <entity>.read for sensitive reads
entity_typetextNOT NULL
entity_iduuid
before_hash, after_hashbyteaSHA-256 of canonical JSON
diff_redactedjsonbC3/C4 values replaced by "***"
ip, user_agent, device_idinet, text, uuid
trace_idtext
occurred_attimestamptzNOT NULLPartition key

sys_idempotency_key​

ColumnTypeConstraintsNotes
keytextUNIQUE with tenant_id, user_id, method, path_templateClient-supplied, ≤ 255 chars
user_iduuidNull for API clients (then api_client_id)
api_client_iduuid
method, path_templatetextNOT NULLFor example POST /lve/requests
request_hashbyteaNOT NULLA different body with the same key → 422
statetextCHECKIN_FLIGHT, COMPLETED
response_statusint
response_bodyjsonbStored for replay
expires_attimestamptzNOT NULL24 h

sys_file_object​

ColumnTypeConstraintsNotes
purposetextCHECKLOGO, SELFIE, EMP_DOCUMENT, CLAIM_BILL, IMPORT, EXPORT, PAYSLIP, STAT_FILE, LMS_CONTENT, CERTIFICATE, ANNOUNCEMENT
object_keytextUNIQUEt/<tenant_id>/<module>/<yyyy>/<mm>/<uuid>
original_nametextC2 (may contain names)
content_typetextNOT NULLChecked against the purpose allowlist
size_bytesbigintNOT NULL
sha256byteaSet after upload
statustextCHECKPENDING_UPLOAD, UPLOADED, CLEAN, INFECTED, DELETED
data_classtextCHECKC0–C4; drives retention
owner_type, owner_idtext, uuidThe entity the file is attached to (authorises downloads)
retain_untildateComputed from the retention schedule
is_immutablebooldefault falseObject Lock prefix

sys_job_run​

The API's "job resource" for asynchronous operations (imports, exports, recomputes).

ColumnTypeConstraintsNotes
job_typetextNOT NULLJob name from the catalogue, for example rpt.export.generate
statustextCHECKQUEUED, RUNNING, SUCCEEDED, FAILED, CANCELLED
progress_pctint0–100
paramsjsonbValidated input
resultjsonbSummary (counts, warnings)
result_file_iduuidFK sys_file_object
errorjsonbproblem+json body
requested_byuuid
started_at, finished_attimestamptz

ORG: organisation and masters​

ColumnTypeConstraintsNotes
legal_nametextNOT NULLRegistered name
pan_enc, pan_last4bytea, textC3, envelope-encrypted
gstintext
tantextTax deduction account number (for TDS)
cintext
registered_statetextISO 3166-2:IN code, for example IN-TG
addressjsonb

Decision pending: whether one tenant may hold several legal entities with separate EPF/ESI registrations. The table exists from R1 either way; with one entity per tenant, it has a single row.

org_location​

ColumnTypeConstraintsNotes
legal_entity_iduuidFK org_legal_entity
codetextUNIQUE per tenantBranch short code, for example KP
nametextNOT NULL
addressjsonbLines, city, district
state_codetextNOT NULLDrives PT and LWF
pin_codetextCHECK 6 digits
timezonetextNOT NULLDefaults to the tenant zone
latitude, longitudenumeric(9,6)Map picker
id_sequence_iduuidFK org_id_sequenceShared or per-branch sequence (SP-ORG-04)
archived_attimestamptz

org_geofence​

ColumnTypeConstraintsNotes
location_iduuidFK org_locationSeveral fences per location
nametext
latitude, longitudenumeric(9,6)NOT NULLCentre
radius_mintCHECK 25–5000Spryple example: 200 m
allowed_bssidsjsonbWi-Fi fallback
qr_secret_reftextRotating QR fallback
is_activebooldefault true

org_department / org_designation / org_grade​

ColumnTypeConstraintsNotes
codetextUNIQUE per tenant
nametextUNIQUE per tenant (case-insensitive)Duplicates rejected (SP-ORG-02)
parent_id (department)uuidFK selfHierarchy
head_employee_id (department)uuidSoft refEMP is downstream of ORG
default_grade_id (designation)uuidFK org_grade
rank (grade)intOrdering for policies ("grade ≥ M2")
archived_attimestamptzBlocked while active employees reference it

org_dept_designation (department_id, designation_id) restricts the designations allowed per department (SP-ORG-07).

org_holiday_calendar / org_location_calendar / org_holiday​

ColumnTypeConstraintsNotes
calendar.name, calendar.yeartext, intUNIQUE (tenant_id, name, year)
location_calendar.location_id, calendar_id, valid_from, valid_touuid, uuid, date, dateno overlap per locationWhich calendar a location uses, effective-dated
holiday.calendar_iduuidFK
holiday.holiday_datedateUNIQUE (calendar_id, holiday_date)No duplicate date per calendar
holiday.nametextNOT NULL
holiday.typetextCHECKPUBLIC, OPTIONAL, RESTRICTED

A change emits org.holiday.changed, which triggers attendance recompute and leave re-quotes.

org_id_sequence​

ColumnTypeConstraintsNotes
scope_keytextUNIQUE per tenantFor example employee:KP or claim
prefixtextNE, CL_GEN_
next_valuebigintNOT NULLLocked with FOR UPDATE when used
pad_lengthintdefault 0

org_custom_field_def​

ColumnTypeConstraintsNotes
entitytextCHECKEMPLOYEE, ACCOUNT, CLAIM, PROJECT
keytextUNIQUE (tenant_id, entity, key)Stored under this key in the entity's custom_fields column
labeltext
data_typetextCHECKTEXT, NUMBER, DATE, BOOLEAN, SELECT, MULTI_SELECT
optionsjsonbFor selects
validation, visibilityjsonb, textRequired flag, ranges, who can see it
reportableboolReportable fields get an expression index
data_classtextCHECKTenants must classify custom fields

org_account / org_contact​

The shared customer/client master used by FFM (CRM) and TSM (projects).

ColumnTypeConstraintsNotes
account.nametextNOT NULL
account.account_typetextTenant-configurable list (hospital, distributor…)
account.gstintextCHECK format
account.address, latitude, longitudejsonb, numericUsed for visit verification
account.owner_employee_iduuidSoft ref
contact.account_iduuidFK
contact.name, phone, emailtext, text, citextC2

IAM: identity and access​

iam_user​

ColumnTypeConstraintsNotes
emailcitextUNIQUE per tenant, nullableLogin identifier
phonetextUNIQUE per tenant, nullableE.164; login for frontline staff
employee_iduuidSoft ref (EMP is downstream of IAM)Null for users who are not employees
usernametextUNIQUE per tenant, nullableOptional
statustextCHECKINVITED, ACTIVE, LOCKED, DISABLED
password_hashtextargon2id; null until activation or for SSO-only users
password_changed_attimestamptz
failed_login_countintLockout per password policy
mfa_requiredboolDerived from roles; can be forced
last_login_attimestamptz
localetext

At least one of email, phone or username is required (CHECK).

iam_identity​

ColumnTypeConstraintsNotes
user_iduuidFK iam_user
sso_connection_iduuidFK iam_sso_connectionThe connection (protocol OIDC or SAML, provider, config, enforce)
subjecttextUNIQUE (tenant_id, sso_connection_id, subject)IdP sub / NameID
email_verifiedboolJIT linking only when true

iam_permission / iam_role / iam_role_permission / iam_role_assignment​

ColumnTypeConstraintsNotes
role.keytextUNIQUE per tenantSeeded keys from the role catalogue (org_owner, hr_admin, …); custom roles get custom_*
role.is_systemboolSystem roles can be cloned, not edited
role.template_keytextThe seeded role it was cloned from
permission.keytextUNIQUE (global table, no tenant_id)<module>.<resource>.<action>, seeded from the RBAC permission matrix; the sensitive flag marks C3/C4 access
role_permission.role_id, permission_iduuidUNIQUE pair
role_permission.max_scopetextCHECKSELF, TEAM, DEPARTMENT, LOCATION, ORG
assignment.user_id, role_iduuidFK
assignment.scopetextCHECKThe granted scope (≤ max_scope)
assignment.filtersjsonbOptional location or department list for LOCATION/DEPARTMENT scopes
assignment.valid_from, valid_todateTime-boxed grants

line_manager is not assigned manually: it is derived from emp_job_assignment.manager_employee_id. See the RBAC permission matrix.

iam_session​

ColumnTypeConstraintsNotes
user_iduuidFK
device_iduuidFK iam_deviceNull for web
family_iduuidNOT NULLRefresh-token family; reuse revokes the family
refresh_token_hashbyteaUNIQUESHA-256 of the current token
client_typetextCHECKWEB, MOBILE, KIOSK, ADMIN
ip, user_agentinet, text
expires_at, revoked_at, last_used_attimestamptz

iam_device​

ColumnTypeConstraintsNotes
user_iduuidFK
platformtextCHECKANDROID, IOS
device_fingerprinttextUNIQUE (tenant_id, user_id, device_fingerprint)Install ID + hardware hints
model, os_version, app_versiontext
kindtextCHECKPERSONAL, KIOSK (push tokens live in mob_push_token)
statustextCHECKPENDING_APPROVAL, ACTIVE, REVOKED
approved_by, approved_atuuid, timestamptzWhen the device-approval policy is on

iam_invite​

ColumnTypeConstraintsNotes
user_iduuidFK
token_hashbyteaUNIQUESingle-use; the raw token is only in the link
channeltextCHECKEMAIL, SMS, WHATSAPP
expires_attimestamptzNOT NULL72 h
used_at, revoked_attimestamptz

iam_mfa_factor / iam_api_client​

ColumnTypeConstraintsNotes
mfa.typetextCHECKTOTP, RECOVERY_CODES
mfa.secret_encbyteaC3, envelope-encrypted
api_client.client_idtextUNIQUE (global)Public API OAuth client
api_client.secret_hashbyteaargon2id
api_client.scopesjsonbPermission keys (scope ORG implied, or narrower)
api_client.ip_allowlistjsonbOptional
api_client.status, last_used_attext, timestamptz

EMP: core HR​

emp_employee​

ColumnTypeConstraintsNotes
employee_codetextUNIQUE per tenantFrom org_id_sequence
first_name, middle_name, last_name, display_nametextfirst and last NOT NULLC2
work_email, personal_emailcitextC2
mobiletextE.164, C2
hired_on, joining_datedatejoining_date NOT NULL
probation_end_date, confirmation_datedate
last_working_datedateSet by EXT
statustextCHECKPRE_JOINING, ACTIVE, ON_NOTICE, EXITED, ANONYMISED
photo_file_iduuidFK sys_file_object
custom_fieldsjsonbValidated against org_custom_field_def
search_tsvtsvectorgenerated, GINName, code, email, phone

emp_job_assignment​

Effective-dated job history. Exclusion constraint: no overlapping ranges per employee.

ColumnTypeConstraintsNotes
employee_iduuidFK
legal_entity_id, location_id, department_id, designation_id, grade_iduuidFK ORG tables; location NOT NULLFacts for policy applicability
manager_employee_iduuidFK emp_employeeDrives line_manager and TEAM scope
cost_center_iduuidFK org_cost_center
employment_typetextCHECKPERMANENT, PROBATION, CONTRACT, INTERN, CONSULTANT, APPRENTICE
work_modetextCHECKOFFICE, FIELD, HYBRID, REMOTE
change_reasontextCHECKJOIN, PROMOTION, TRANSFER, REORG, CORRECTION, CONFIRMATION
valid_from, valid_todateinclusiveEmits emp.job.changed

emp_reporting_closure​

A closure table rebuilt from the current manager_employee_id chain; used by the TEAM scope guard.

ColumnTypeConstraintsNotes
ancestor_id, descendant_iduuidPK (with tenant_id)
depthintNOT NULL0 = self, 1 = direct report

emp_personal​

ColumnTypeConstraintsNotes
employee_iduuidFK, UNIQUEOne row per employee
date_of_birthdateC2
gendertextCHECKFEMALE, MALE, NON_BINARY, UNDISCLOSED; never used for leave eligibility except where the law requires it
aadhaar_enc, aadhaar_hmac, aadhaar_last4bytea, bytea, textaadhaar_hmac UNIQUE per tenantC4, envelope-encrypted; HMAC for duplicate detection
pan_enc, pan_hmac, pan_last4bytea, bytea, textC3
blood_grouptextC3 (health)
residence_address, permanent_address, emergency_contactjsonbC2
key_idtextNOT NULLThe tenant data-key version

UAN and ESIC numbers live in pay_employee_statutory. Reading the encrypted columns needs emp.sensitive.read, and every read is audited.

emp_bank_account​

ColumnTypeConstraintsNotes
employee_iduuidFK
ifsctextCHECK IFSC format (4 letters, 0, 6 alphanumerics)
account_no_enc, account_last4bytea, textC3
holder_nametextName-match check against the employee
is_primaryboolpartial UNIQUE (tenant_id, employee_id) WHERE primary
statustextCHECKUNVERIFIED, VERIFIED, FAILED, INACTIVE
valid_from, valid_todatePayroll uses the account valid at pay date

emp_family_member / emp_education / emp_experience​

ColumnTypeConstraintsNotes
family.name, relationship, date_of_birthtext, text, dateC3
family.is_nominee, nomination_pctbool, numeric(5,2)nominees sum to 100 per schemeEPF, gratuity nominations
education.qualification, institution, yeartext, text, intC2
experience.employer, designation, from_date, to_datetext, text, date, dateC2

emp_document​

ColumnTypeConstraintsNotes
employee_iduuidFK
doc_typetextTenant list (PAN copy, relieving letter, …)
file_iduuidFK sys_file_object
statustextCHECKSUBMITTED, APPROVED, REJECTED, SUPERSEDED; HR uploads are auto-approved (SP-EMP-08)
reviewed_by, reviewed_at, reject_reasonuuid, timestamptz, text
expires_ondateFor visas and licences

emp_checklist_template / emp_checklist_item / emp_task​

ColumnTypeConstraintsNotes
template.kindtextCHECKONBOARDING, OFFBOARDING
template.applicabilityjsonbDepartments, locations; null = all
item.title, sort_ordertext, int
item.owner_type, owner_reftextDEPARTMENT, ROLE, USER, MANAGER: each item has an owner (Spryple screenshot evidence)
item.due_offset_days, evidence_requiredint, boolRelative to joining or LWD
task.employee_id, item_iduuidFK; UNIQUE (employee_id, item_id, context_id)
task.context, context_idtext, uuidCHECK contextONBOARDING, OFFBOARDING (exit clearance), INDUCTION
task.owner_user_id, due_dateuuid, date
task.statustextCHECKPENDING, DONE, NOT_APPLICABLE, OVERDUE
task.commenttext

Append-only (withdrawal sets withdrawn_at through a dedicated function).

ColumnTypeConstraintsNotes
employee_iduuidFK
purposetextCHECKFACE_BIOMETRIC, LOCATION_TRACKING, SELFIE_CAPTURE, WHATSAPP_MESSAGES, DATA_PROCESSING_NOTICE
notice_versiontextNOT NULLThe text the employee saw
statustextCHECKGIVEN, WITHDRAWN
given_at, withdrawn_attimestamptz
channel, device_idtext, uuidEvidence

emp_import_batch​

ColumnTypeConstraintsNotes
import_typetextCHECKEMPLOYEES, BANK, COMPENSATION, OPENING_LEAVE, YTD_PAYROLL
template_versiontextNOT NULL
file_id, error_report_file_iduuidFK
statustextCHECKUPLOADED, VALIDATING, VALIDATED, COMMITTING, COMMITTED, FAILED
row_count, error_count, committed_countint

ATT: attendance​

Aligned with the Attendance module spec.

att_policy / att_policy_version / att_policy_assignment​

The same three-table shape is used by every module with policies (lve_, pay_, clm_, …).

ColumnTypeConstraintsNotes
policy.codetextUNIQUE per tenant
policy.kindtextNOT NULLatt.attendance, att.overtime
policy.is_defaultboolone default per kind (partial UNIQUE)Seeded at provisioning
version.policy_iduuidFK
version.version_nointUNIQUE (policy_id, version_no)
version.schema_versiontextNOT NULLSemver of the kind's schema
version.settingsjsonbNOT NULLValidated by packages/policy
version.statustextCHECKDRAFT, PUBLISHED, SUPERSEDED; published rows are immutable
version.valid_from, valid_todateno overlap among published versions
version.published_by, published_atuuid, timestamptz
assignment.applicabilityjsonbNOT NULLRule over job-assignment facts
assignment.priorityintdefault 100Tie-breaker after specificity
assignment.valid_from, valid_todate

att_shift​

ColumnTypeConstraintsNotes
code, nametextcode UNIQUE per tenant
start_time, end_timetimeNOT NULLLocal to the location
crosses_midnightboolgenerated (end_time <= start_time)Night shifts
is_flexiblebool
flex_core_minutesintRequired hours for flexible shifts
break_minutesintDefault break
early_window_minutes, late_window_minutesintPunch window around the shift
colortextRoster UI

att_rotation / att_rotation_step / att_weekoff_pattern​

ColumnTypeConstraintsNotes
rotation.location_iduuidFK org_locationRotations are per location (SP-ATT-07)
rotation.cycle_daysintSum of step days
step.step_nointUNIQUE (rotation_id, step_no)
step.shift_id, daysuuid, intFK
weekoff.rulejsonbWeekly days plus monthly rules, for example "every Sunday, and the 2nd and 4th Saturday"

att_shift_assignment​

Effective-dated; exclusion constraint per employee.

ColumnTypeConstraintsNotes
employee_iduuidFK
shift_iduuidFK, nullableEither a shift or a rotation (CHECK)
rotation_id, rotation_start_stepuuid, intFK
weekoff_pattern_iduuidFK
valid_from, valid_todateA change triggers att.range.recompute
sourcetextCHECKMANUAL, DEFAULT_RULE, SWAP, IMPORT

att_device / att_device_user_map​

ColumnTypeConstraintsNotes
device.serial_notextUNIQUE (global)Identifies the tenant at ingest
device.vendor, modetextCHECK modePUSH, PULL_AGENT, CSV
device.secret_hashbyteaPer-device secret
device.location_id, last_seen_atuuid, timestamptzHealth monitoring
map.device_user_codetextUNIQUE (device_id, device_user_code, valid_from)Device enrolment number
map.employee_id, valid_from, valid_touuid, dateSP-ATT-13

att_punch​

Append-only, partitioned monthly by punched_at. PK (id, punched_at).

ColumnTypeConstraintsNotes
employee_iduuidNOT NULLNo FK into or out of partitions; validated by the service
punched_attimestamptzNOT NULLServer-derived for offline punches
directiontextCHECKIN, OUT, UNKNOWN (devices often don't know)
sourcetextCHECKWEB, MOBILE, KIOSK, BIOMETRIC, IMPORT, MANAGER, FIELD
device_id, kiosk_iduuid
client_refuuidUNIQUE (tenant_id, client_ref, punched_at)Offline-queue idempotency
device_time, received_attimestamptzSkew detection
latitude, longitude, accuracy_mnumericC4
geofence_id, geofence_resultuuid, textCHECK resultINSIDE, OUTSIDE, NO_FIX, NOT_REQUIRED, WIFI_OK, QR_OK
selfie_object_keytextC4; nulled after 180 days
face_match_result, face_score, liveness_scoretext, numeric, numericMATCH, MISMATCH, NOT_CHECKED
dedupe_keytextHash of employee, minute bucket, direction, source family
statustextCHECKACCEPTED, FLAGGED, REJECTED, DUPLICATE
reasontextManager entry or rejection reason

att_day​

A rebuildable projection: one row per employee per work date. UNIQUE (tenant_id, employee_id, work_date).

ColumnTypeConstraintsNotes
employee_id, work_dateuuid, dateNOT NULLWork date = local date of the shift start
shift_id, policy_version_iduuidFK
statustextCHECKP, A, HD, W, H, L, HL, WP, HP, OD, WFH, NJ, SEP
first_half, second_halftextCHECK (same set)The day status is derived from the halves
paid_fractionnumeric(3,2)CHECK IN (0, 0.5, 1)
first_in, last_outtimestamptz
worked_minutes, break_minutes, late_minutes, early_out_minutes, permission_minutesint≥ 0
ot_minutes, ot_approved_minutesintEligible versus approved
is_late, missed_punchbool
flagsjsonbGEOFENCE_EXCEPTION, FACE_MISMATCH, MULTI_SOURCE
input_hashtextNOT NULLRecompute is skipped when unchanged
engine_versiontext
is_lockedboolSet by att_period_lock
computed_attimestamptz

att_request​

All attendance request types in one table (work-type requests, regularization, permission, shift change, OT claim).

ColumnTypeConstraintsNotes
employee_iduuidFK
typetextCHECKWORK_TYPE, REGULARIZATION, PERMISSION, SHIFT_CHANGE, OVERTIME
sub_typetextWFH, WFO, OD, REMOTE; MISSED_OUT, MISSED_IN; SWAP
from_date, to_datedatefrom_date <= to_date
from_half, to_halftextCHECKFIRST, SECOND, FULL
minutesintPermission or OT minutes
payloadjsonbType-specific (corrected times, target shift, counterpart employee)
statustextCHECKDRAFT, SUBMITTED, IN_APPROVAL, AWAITING_COUNTERPART, APPROVED, REJECTED, WITHDRAWN, CANCELLATION_REQUESTED, CANCELLED
on_behalf, requested_bybool, uuidOn-behalf requests are auto-approved
reason, attachment_file_idtext, uuid
workflow_instance_iduuidFK ntf_instance

att_leave_mark​

A projection maintained from LVE events (lve.request.approved, lve.request.cancelled). The day computer reads it so ATT never calls LVE.

ColumnTypeConstraintsNotes
employee_id, leave_date, halfuuid, date, textUNIQUE (tenant_id, employee_id, leave_date, half)
leave_type_code, is_paidtext, bool
lve_request_iduuidSoft ref

att_period_lock / att_adjustment​

ColumnTypeConstraintsNotes
lock.pay_period_iduuidSoft ref (PAY is downstream)
lock.period_start, period_enddateno overlap per tenant and pay schedule
lock.statustextCHECKOPEN, PRE_LOCK_CHECK, LOCKED, CLOSED
lock.locked_at, locked_by, override_reasontimestamptz, uuid, text
adjustment.employee_id, work_dateuuid, dateA post-lock change
adjustment.paid_fraction_delta, ot_minutes_deltanumeric(3,2), int
adjustment.target_pay_period_iduuidSoft refThe period whose run settles it (via pay_input)
adjustment.statustextCHECKPENDING, APPLIED, WAIVED

mob_kiosk_device / mob_face_profile​

Owned by MOB. MOB also owns mob_app_install, mob_push_token, mob_sync_batch and mob_kiosk_punch_batch (sync bookkeeping).

ColumnTypeConstraintsNotes
kiosk.location_id, iam_device_iduuidFKThe kiosk token is an iam_session on a KIOSK device
kiosk.name, modetextCHECK modeFACE, PIN, FACE_OR_PIN
kiosk.statustextCHECKPENDING_ENROLMENT, ACTIVE, REVOKED
face.employee_iduuidFK, UNIQUE
face.providertext
face.template_ref_encbyteaC4: provider face ID or local template, envelope-encrypted
face.enrolled_by, enrolled_atuuid, timestamptz
face.statustextCHECKNOT_ENROLLED, VERIFIED, REVOKED
face.consent_iduuidFK emp_consentRequired (NOT NULL)

LVE: leave​

Aligned with the Leave module spec.

lve_type​

ColumnTypeConstraintsNotes
codetextUNIQUE per tenantCL, SL, EL, LOP, COMP_OFF, …
name, colortext
categorytextCHECKPAID, UNPAID, COMP_OFF, STATUTORY_PARENTAL, SPECIAL
unittextCHECKDAY, HALF_DAY, HOUR
template_codetextSeed template it came from
is_activebool

lve_policy (leave_type_id, name) with lve_policy_version (adds transition_mode: how existing balances move to the new version) and lve_policy_assignment follow the shared policy shape.

lve_cycle​

ColumnTypeConstraintsNotes
cycle_start, cycle_enddateno overlap per tenantApr–Mar or Jan–Dec
statustextCHECKOPEN, CLOSING, CLOSED

lve_ledger_entry​

Append-only. UNIQUE (tenant_id, source_type, source_id, entry_type).

ColumnTypeConstraintsNotes
employee_id, leave_type_id, cycle_iduuidFKThe ledger stream
seqbigintUNIQUE per streamMonotonic
entry_typetextCHECKOPENING, ACCRUAL, PRORATA_ACCRUAL, AVAIL, AVAIL_REVERSAL, ADJUSTMENT, CARRY_FORWARD_OUT, CARRY_FORWARD_IN, LAPSE, ENCASHMENT, COMP_OFF_CREDIT, COMP_OFF_EXPIRY, LATE_DEDUCTION, ADVANCE, FNF_SETTLEMENT
daysnumeric(6,2)≠ 0Signed
effective_datedateNOT NULL
source_type, source_idtext, uuidNOT NULLRequest, accrual run, adjustment, event
policy_version_iduuidFK lve_policy_version
reasontextrequired for ADJUSTMENT
reverses_entry_iduuidFK self

lve_balance​

The projection of the ledger. UNIQUE (tenant_id, employee_id, leave_type_id, cycle_id).

ColumnTypeConstraintsNotes
balancenumeric(6,2)Sum of entries
reservednumeric(6,2)≥ 0Submitted but not approved requests
availed_ytdnumeric(6,2)
last_entry_seqbigintConsistency check

lve_request / lve_request_day​

ColumnTypeConstraintsNotes
request.employee_id, leave_type_iduuidFK
request.from_date, to_date, from_half, to_halfdate, date, text, text
request.requested_days, charged_daysnumeric(6,2)Charged includes sandwiched days
request.statustextCHECKDRAFT, SUBMITTED, IN_APPROVAL, APPROVED, REJECTED, WITHDRAWN, CANCELLATION_REQUESTED, CANCELLED
request.sourcetextCHECKSELF, ON_BEHALF, REGULARIZATION, IMPORT
request.reason, contact_during_leavetextC2
request.attachment_file_iduuidFKMedical certificate above N days (C3)
request.workflow_instance_iduuidFK
day.leave_date, halfdate, textUNIQUE (request_id, leave_date, half)
day.day_kindtextCHECKWORKING, WEEK_OFF, HOLIDAY
day.chargenumeric(3,2)IN (0, 0.5, 1)
day.sandwichedbool

An exclusion constraint on approved and pending requests prevents overlapping leave for the same employee and half.

lve_comp_off_credit / lve_encashment​

ColumnTypeConstraintsNotes
credit.employee_id, worked_dateuuid, dateUNIQUEOne credit per worked off-day
credit.worked_minutes, daysint, numeric(3,2)Half or full credit
credit.expires_ondateFIFO use by expiry
credit.statustextCHECKREQUESTED, CREDITED, PARTIALLY_USED, USED, EXPIRED, REJECTED
encashment.daysnumeric(6,2)
encashment.triggertextCHECKCYCLE_END, REQUEST, FNF
encashment.statustextCHECKPENDING, APPROVED, PAID, REJECTED
encashment.pay_input_iduuidSoft ref to pay_inputPAY is downstream

PAY: payroll​

Table names follow the Payroll module spec. Amounts are stored as bigint paise (*_paise), per the data model overview.

pay_component​

ColumnTypeConstraintsNotes
codetextUNIQUE per tenantBASIC, HRA, SPL, EPF_EE, …
name, payslip_labeltextRenamable label (SP-PAY-05)
kindtextCHECKEARNING, DEDUCTION, EMPLOYER_CONTRIBUTION, REIMBURSEMENT, INFORMATIONAL
calc_typetextCHECKFLAT, PERCENT, FORMULA, STATUTORY, INPUT, BALANCING
taxable, pf_wage, esi_wage, pt_wage, gratuity_wage, prorate, part_of_ctcboolStatutory wage bases and CTC treatment
statutory_codetextLinks statutory components to engine rules (EPF_EE, ESI_ER, PT, LWF_EE, TDS)
roundingtextCHECKNONE, NEAREST_RUPEE, UP_RUPEE, DOWN_RUPEE
display_orderint

pay_structure / pay_structure_version / pay_structure_line​

A salary structure template, versioned. It replaces Spryple's "pay group by CTC range".

ColumnTypeConstraintsNotes
structure.code, nametextcode UNIQUE per tenant
structure.suggested_forjsonbOptional applicability hint for the assignment UI
version.structure_id, version_nouuid, intUNIQUE pair
version.statustextCHECKDRAFT, ACTIVE, RETIRED; active versions are immutable
version.valid_from, valid_todate
line.structure_version_id, component_iduuidFK; UNIQUE pair
line.formulatextSandboxed expression (flat, % of CTC/Basic, slab)
line.is_balancingboolone per versionAbsorbs the CTC remainder (special allowance)

pay_compensation / pay_compensation_line​

Effective-dated compensation per employee. Class C3. Exclusion constraint per employee.

ColumnTypeConstraintsNotes
employee_id, structure_version_iduuidFK
annual_ctc_paisebigint> 0
reasontextCHECKJOIN, INCREMENT, PROMOTION, CORRECTION, RESTRUCTURE
valid_from, valid_todateBack-dated changes create arrears inputs
approved_byuuidSegregation of duties against run approval
line.component_iduuidFK; UNIQUE (compensation_id, component_id)Resolved breakdown
line.monthly_paise, annual_paisebigint

pay_employee_statutory​

Effective-dated statutory profile. Class C3.

ColumnTypeConstraintsNotes
employee_iduuidFK
uan, esic_ip_notextEPF UAN and ESIC insurance number
pf_member, pf_wage_cappedboolElection of capped or actual PF wages (examples; verify scheme rules)
vpf_percentnumeric(9,4)Voluntary PF
pt_state, lwf_statetextUsually the work location's state
tax_regimetextCHECKNEW, OLD
valid_from, valid_todate

pay_schedule / pay_period​

ColumnTypeConstraintsNotes
schedule.legal_entity_iduuidFK
schedule.frequencytextCHECKMONTHLY (others later)
schedule.period_start_dayint1–281 = calendar month; 25 = 25th to 24th (SP-PAY-04)
schedule.salary_basistextCHECKCALENDAR, ORG_WORKING_DAYS, FIXED
schedule.fixed_basis_days, pay_day, attendance_cutoff_dayint
period.period_start, period_end, pay_datedateUNIQUE (schedule_id, period_start)
period.att_window_start, att_window_enddateAttendance window may differ from the pay period
period.financial_yeartext2026-27
period.statustextCHECKOPEN, IN_PROGRESS, CLOSED

pay_run​

ColumnTypeConstraintsNotes
period_iduuidFK
run_typetextCHECKREGULAR, OFF_CYCLE, BONUS, FNF, REVERSAL
statustextCHECKDRAFT, PREPARED, CALCULATING, CALCULATED, REVIEWED, APPROVED, LOCKED, PAID, REVERSED, CANCELLED
calc_versionintIncremented by each recalculation
engine_version, stat_pack_versiontextFrozen at prepare
reverses_run_iduuidFK self
employee_count, total_gross_paise, total_net_paiseint, bigint, bigint
prepared_by, approved_by, locked_atuuid, uuid, timestamptz
workflow_instance_iduuidFK ntf_instanceRun approval

At most one non-cancelled REGULAR run per period (partial UNIQUE).

pay_run_employee​

One row per employee per run. UNIQUE (tenant_id, run_id, employee_id). Immutable after lock (trigger). Class C3.

ColumnTypeConstraintsNotes
run_id, employee_id, compensation_iduuidFK
statustextCHECKPENDING, CALCULATED, ERROR, ON_HOLD, EXCLUDED
basis_days, payable_days, lop_daysnumeric(6,2)
gross_paise, total_deductions_paise, net_pay_paise, employer_cost_paisebigint
input_snapshotjsonbNOT NULL after calculationThe exact engine input
input_hashtextSHA-256 hex of canonical JSON
output_snapshotjsonbThe engine output
engine_versiontext
warningsjsonbVariance flags, minimum-wage check, negative net
hold_reasontextSalary hold

pay_run_line​

One component amount for one employee in one run. Class C3. Immutable after lock.

ColumnTypeConstraintsNotes
run_iduuidFK pay_runDenormalised so the lock trigger and run-level queries need no join
run_employee_id, component_iduuidFK; UNIQUE pair
base_paise, ratebigint, numeric(9,4)For example the EPF wage base and 12.0000
amount_paisebigintRounded
ytd_paisebigintFinancial year to date
sourcetextCHECKSTRUCTURE, INPUT, STATUTORY, LOAN, ATTENDANCE

pay_input​

One-time inputs for a period: arrears, variable pay, bonus, reimbursements (from claims), encashment (from leave), attendance adjustments, TDS override, other deductions.

ColumnTypeConstraintsNotes
employee_id, period_id, component_iduuidFK
input_typetextCHECKARREAR, VARIABLE_PAY, BONUS, REIMBURSEMENT, ENCASHMENT, TDS_OVERRIDE, OTHER_DEDUCTION, ATT_ADJUSTMENT
amount_paise, quantitybigint, numeric(9,2)Signed amount for adjustments
source_module, source_idtext, uuidUNIQUE (tenant_id, source_module, source_id)Idempotent from clm.claim.approved, lve.encashment.approved, att.adjustment.created
statustextCHECKPENDING, CONSUMED, CANCELLED

pay_payslip / pay_bank_file / pay_statutory_file​

ColumnTypeConstraintsNotes
payslip.run_employee_iduuidFK, UNIQUE
payslip.payslip_notextUNIQUE per tenant
payslip.file_id, password_protected, published_atuuid, bool, timestamptzObject Lock
bank_file.run_id, debit_account_iduuidFK (org_bank_account)
bank_file.bank_formattextNEFT_GENERIC, bank-specific adapters
bank_file.file_id, total_paise, row_count, statusuuid, bigint, int, textGENERATED, UPLOADED, CONFIRMED, FAILED
statutory_file.scheme, statetextEPF_ECR, ESIC_MC, PT, LWF, TDS_24Q
statutory_file.adapter_version, file_id, statustext, uuid, textRegeneration creates a new row

pay_loan / pay_loan_ledger​

Salary advances (SP-PAY-07) and loans.

ColumnTypeConstraintsNotes
loan.loan_typetextCHECKSALARY_ADVANCE, LOAN
loan.principal_paise, instalment_paise, outstanding_paisebigintoutstanding_paise is the ledger projection
loan.interest_rate, instalments, first_recovery_period_idnumeric(9,4), int, uuid
loan.statustextCHECKREQUESTED, APPROVED, ACTIVE, CLOSED, WRITTEN_OFF, REJECTED
ledger.entry_typetextCHECKDISBURSAL, RECOVERY, ADJUSTMENT, FNF_RECOVERY, WRITE_OFF
ledger.seq, amount_paise, effective_datebigint, bigint, dateappend-only
ledger.run_employee_iduuidThe recovering run row

pay_tax_declaration / pay_tax_proof​

Class C3.

ColumnTypeConstraintsNotes
declaration.employee_id, financial_yearuuid, textUNIQUE pair
declaration.regimetextCHECKNEW, OLD
declaration.items, previous_employerjsonbSection-wise amounts, rent, prior income and TDS
declaration.statustextCHECKDRAFT, SUBMITTED, LOCKED, PROOF_WINDOW, VERIFIED
proof.item_code, claimed_paise, approved_paisetext, bigint, bigint
proof.file_id, statusuuid, text

pay_statutory_registration​

ColumnTypeConstraintsNotes
legal_entity_iduuidFK
schemetextCHECKEPF, ESI, PT, LWF, TAN
statetextPer state for ESI, PT and LWF (SP-PAY-03)
registration_notextNOT NULL
valid_from, valid_todate

pay_statutory_rate (global reference)​

No tenant_id; read-only to the app; imported from the control plane's published statutory pack. A tenant's runs record which pack_version they used.

ColumnTypeConstraintsNotes
schemetextEPF, ESI, PT, LWF, TDS, GRATUITY, BONUS, MIN_WAGE
statetextNull for national schemes
pack_versiontextNOT NULLFor example 2026.10.1
rate_tablejsonbRates as decimal strings, slabs as arrays. All values are examples to verify.
valid_from, valid_todate

NTF: notifications and workflow​

Table names follow the Notifications & Workflow module spec.

ntf_workflow_def / ntf_workflow_version / ntf_workflow_step​

ColumnTypeConstraintsNotes
def.request_typetextlve.request, att.request, clm.claim, pay.run, ext.separation, …
version.def_id, version_nouuid, intUNIQUE pair
version.on_behalf_modetextCHECKAUTO_APPROVE, SKIP_OWN_STEP, NORMAL
version.applicability, priority, valid_from, valid_tojsonb, int, date, dateSame resolution as policies
step.step_nointUNIQUE (version_id, step_no)
step.resolver, resolver_argstext, jsonbMANAGER (level N), DEPT_HEAD, ROLE + scope, USER, EMPLOYEE_FIELD
step.conditionjsonbExpression over the instance context (decision pending: JSONLogic or a CEL subset)
step.modetextCHECKANY, ALL
step.remind_after_hours, escalate_after_hours, escalate_to, timeout_actionint, int, jsonb, textSLA handling

ntf_instance​

ColumnTypeConstraintsNotes
version_iduuidFKPinned at start
request_type, subject_idtext, uuidpartial UNIQUE while PENDINGOne live instance per subject
requester_employee_id, initiator_user_iduuidDiffer for on-behalf requests
current_stepint
statustextCHECKPENDING, APPROVED, REJECTED, WITHDRAWN, CANCELLED
contextjsonbFacts captured at start (C0–C2)

ntf_task / ntf_action​

ColumnTypeConstraintsNotes
task.instance_id, step_nouuid, int
task.assignee_user_id, original_assignee_user_iduuidFK iam_userIndex (tenant_id, assignee_user_id, status) for the inbox
task.statustextCHECKOPEN, APPROVED, REJECTED, DELEGATED, ESCALATED, SKIPPED, EXPIRED
task.due_at, escalation_leveltimestamptz, int
action.actor_user_id, actionuuid, textappend-only; action CHECKAPPROVE, REJECT, SEND_BACK, REASSIGN, COMMENT
action.commenttextrequired for REJECT
action.auto, acted_atbool, timestamptzAuto-approval and SLA actions are marked

ntf_delegation​

ColumnTypeConstraintsNotes
delegator_user_id, delegate_user_iduuidFK; CHECK they differ
request_typesjsonbNull = all
valid_from, valid_todate

ntf_template / ntf_message / ntf_delivery / ntf_preference​

ColumnTypeConstraintsNotes
template.event_key, channel, locale, version_notext, text, text, intUNIQUE setTenant overrides shadow platform defaults (rows with a null tenant_id are platform defaults under a separate read-only policy)
template.subject, bodytextHandlebars (sandboxed)
message.recipient_user_id, event_key, channeluuid, text, textpartitioned monthly by created_atIN_APP, EMAIL, SMS, WHATSAPP, PUSH
message.status, read_attext, timestamptzQUEUED, SENT, DELIVERED, FAILED, SUPPRESSED
delivery.message_id, provider, provider_ref, status, attemptuuid, text, text, text, intOne row per provider attempt
preference.user_id, event_key, channelsuuid, text, jsonbSecurity messages can't be disabled

ntf_webhook_subscription / ntf_webhook_delivery​

ColumnTypeConstraintsNotes
subscription.urltextCHECK https://SSRF checks at create and at send
subscription.event_typesjsonbWebhook-exposed events only
subscription.secret_enc, secret_next_encbyteaHMAC secrets; two active during rotation
subscription.active, consecutive_failuresbool, intCircuit breaker
delivery.subscription_id, outbox_event_id, attemptuuid, uuid, intUNIQUE triple; partitioned monthly
delivery.status_code, duration_msint
delivery.statustextCHECKPENDING, SUCCEEDED, FAILED_RETRYING, DEAD_LETTERED, REPLAYED
delivery.next_attempt_attimestamptz

RPT: reporting​

TableKey columnsNotes
rpt_datasetPK key, module, columns, filters, required_permissionPlatform-defined (no tenant_id), for example att.monthly_register, pay.register
rpt_saved_viewowner_user_id, dataset_key, columns, filters, sharedScope is applied at run time from the viewer's grants
rpt_scheduleview_id, cron, format (XLSX, CSV, PDF), recipients, activeRuns in the tenant time zone
rpt_export_jobrequested_by, dataset_key, params, format, status, row_count, file_id, expires_atThe API's job resource for exports
rpt_dashboard / rpt_widgetpersona, layout; widget dataset_key, chart_type, aggregationPersona dashboards

Other asynchronous operations (imports, recomputes) use sys_job_run.


CLM: claims​

Table names follow the Claims module spec.

clm_category​

ColumnTypeConstraintsNotes
code, nametextUNIQUE per tenantFood, travel, mileage, lodging…
kindtextCHECKRECEIPT, MILEAGE, PER_DIEM
receipt_required, gst_applicable, is_activebool

Expense limits live in clm_policy / clm_policy_version / clm_policy_assignment (shared policy shape, kind clm.expense).

clm_claim​

ColumnTypeConstraintsNotes
claim_notextUNIQUE per tenantFrom org_id_sequence
employee_iduuidFK
sourcetextCHECKMANUAL, MILEAGE_FROM_TRAVEL
requested_paise, verified_paise, approved_paisebigint
statustextCHECKDRAFT, SUBMITTED, SENT_BACK, VERIFIED, APPROVED, PAID, REJECTED, WITHDRAWN
payout_modetextCHECKPAYROLL, BANK_TRANSFER, CASH
policy_version_iduuidFKLimits applied at submission
workflow_instance_iduuidFK ntf_instanceVerify, then approve
payout_batch_iduuidFK

clm_line / clm_attachment​

ColumnTypeConstraintsNotes
line.claim_id, category_iduuidFK
line.expense_date, bill_no, vendor_name, vendor_gstindate, text, text, text
line.amount_paise, gst_paise, quantitybigint, bigint, numeric(9,2)Quantity = km for mileage
line.verified_paisebigintPer-line verified amount (observed in Spryple)
line.line_statustextCHECKPENDING, ACCEPTED, REDUCED, REJECTED
line.policy_resultjsonbLimit checks at submission
line.duplicate_hashbyteaindexedBill number + amount + date + vendor
line.source_refuuidffm_daily_travel row for mileage lines
attachment.line_id, file_id, image_phashuuid, uuid, byteaPerceptual hash for duplicate images

clm_advance / clm_ledger_entry / clm_payout_batch​

ColumnTypeConstraintsNotes
advance.employee_id, amount_paise, purpose, statusuuid, bigint, text, textTravel advances, settled against claims
ledger.employee_id, entry_typeuuid, textappend-onlyADVANCE_PAID, CLAIM_APPROVED, ADVANCE_SETTLED, PAYOUT, RECOVERY
ledger.amount_paise, source_type, source_id, effective_datebigint, text, uuid, dateUNIQUE (source_type, source_id, entry_type)
batch.mode, pay_period_id, total_paise, statustext, uuid, bigint, textpay_period_id soft refPayroll or bank-file payout

EXT: exit and full-and-final​

ext_reason​

ColumnTypeConstraintsNotes
kindtextCHECKRESIGNATION, TERMINATION, RETIREMENT, DEATH, ABSCONDING, CONTRACT_END
name, is_activetext, boolUNIQUE (kind, name)

ext_separation / ext_lwd_proposal​

ColumnTypeConstraintsNotes
employee_iduuidFK; one open separation per employee
separation_type, reason_idtext, uuid
requested_on, requested_lwd, approved_lwddate
notice_days_required, notice_days_servedintFrom the ext.notice policy
notice_treatmenttextCHECKSERVE, RECOVER, WAIVE, PAY_IN_LIEU
statustextCHECKSUBMITTED, IN_APPROVAL, APPROVED, REJECTED, WITHDRAWN, CLEARANCE, SETTLED, CLOSED
rehire_eligiblebool
workflow_instance_iduuidFKEmployee → line manager → HR
lwd_proposal.proposed_by, proposed_lwd, noteuuid, date, textappend-onlyLWD negotiation history

Clearance items are emp_task rows with context = OFFBOARDING and context_id = the separation.

ext_exit_interview / ext_fnf_settlement / ext_fnf_line​

ColumnTypeConstraintsNotes
interview.answers, statusjsonb, textC2; restricted to HR (ext.interview.read)
settlement.separation_iduuidFK, UNIQUE
settlement.pay_run_iduuidFK pay_run (EXT is downstream of PAY)An FNF run
settlement.total_payable_paise, total_recoverable_paise, net_paisebigint
settlement.due_date, statusdate, textCHECK statusDRAFT, PREPARED, APPROVED, PAID, CLOSED
line.itemtextCHECKSALARY_TILL_LWD, LEAVE_ENCASHMENT, GRATUITY, NOTICE_PAY, NOTICE_RECOVERY, LOAN_RECOVERY, ASSET_RECOVERY, BONUS, OTHER
line.quantity, amount_paise, basisnumeric(9,2), bigint, text

ENG: engagement​

TableKey columnsNotes
eng_announcementtopic, title, body, publish_from, publish_to, ack_required, pinned, status (DRAFT, SCHEDULED, PUBLISHED, STOPPED, COMPLETED, CANCELLED), author_user_idSpryple statuses (SP-ENG-01) plus targeting
eng_announcement_audienceannouncement_id, rule jsonb, resolved_countLocations, departments, designations
eng_announcement_readannouncement_id, employee_id UNIQUE pair, read_at, acknowledged_atRead receipts
eng_recognition_typename, icon, manager_only, is_activeBirthday, Job Well Done, …
eng_recognitiontype_id, from_employee_id, to_employee_id, message (≤ 280 chars), visibility, sent_atCHECK sender ≠ receiver
eng_reactionrecognition_id, employee_id, emoji_codeUNIQUE per employee and code
eng_celebrationemployee_id, kind (BIRTHDAY, WORK_ANNIVERSARY), celebration_dateGenerated daily; respects the employee's privacy setting

FFM: field force and CRM​

Table names follow the Field Force & CRM module spec; accounts are the shared org_account.

TableKey columnsNotes
ffm_pipeline / ffm_stagepipeline name, template_code; stage name, sort_order, probability, is_won, is_lostConfigurable stages replace the demo-centric pipeline
ffm_opportunityaccount_id, pipeline_id, stage_id, owner_employee_id, expected_value_paise, final_value_paise, stage_entered_on, statusLead age = today − stage_entered_on
ffm_associateaccount_id, associate_type, name, qualification, specializationFor example Doctor, MBBS, Cardiology
ffm_activityaccount_id, opportunity_id, employee_id, activity_type (VISIT, CALL, MESSAGE, MAIL, DEMO), due_at, done_at, outcomeFollow-ups
ffm_visitaccount_id, employee_id, beat_stop_id, checked_in_at, checked_out_at, latitude, longitude (C4), distance_from_account_m, location_result (MATCHED, NOT_MATCHED, NOT_AVAILABLE), photo_file_id, client_ref UNIQUEEnforcement mode from the ffm.tracking policy
ffm_beat_plan / ffm_beat_stopplan employee_id, plan_date UNIQUE pair, status; stop account_id, sequenceRoute plans
ffm_track_sessionemployee_id, work_date, mode (POINT_TO_POINT, CONTINUOUS), consent_id NOT NULL, started_at, ended_atOnly between punch-in and punch-out
ffm_location_pointPK (id, recorded_at), session_id, latitude, longitude, accuracy_m, speed_mps, battery_pct, is_mockC4; monthly partitions; 90-day retention; no FKs
ffm_daily_travelsession_id, employee_id, work_date, computed_m, revised_m, revise_reason, visit_count, status (PENDING, VERIFIED, APPROVED, CLAIMED, REJECTED), claim_idDistances in metres; feeds CLM mileage claims
ffm_paymentopportunity_id, method, amount_paise, collected_at, collected_byField collections

TSM: timesheets​

TableKey columnsNotes
tsm_projectaccount_id, code UNIQUE, name, manager_employee_id, start_date, end_date, estimated_minutes, billable_default, status
tsm_project_memberproject_id, employee_id, project_role, allocation_pct, bill_rate_paise, valid_from, valid_toBench = active employees with no current membership
tsm_taskproject_id, name, assignee_employee_id, planned_minutes, planned_start, planned_end, statusEffort variance = (actual − planned) ÷ planned
tsm_timesheetemployee_id, week_start UNIQUE pair, total_minutes, status (DRAFT, SUBMITTED, APPROVED, REJECTED), workflow_instance_idWeekly grid
tsm_entrytimesheet_id, task_id, work_date, minutes, billable, progress_pct, descriptionOptional cap: daily total ≤ att_day.worked_minutes
tsm_period_lockperiod_start, period_end, status

Durations are stored as minutes (the module spec shows hours in the UI).


LMS: learning​

TableKey columnsNotes
lms_coursetitle, category, difficulty, content_type (NATIVE, SCORM), scorm_package_file_id, instructor_user_id, recurrence_months, statusMandatory compliance courses first (POSH, safety)
lms_module / lms_lessonmodule course_id, title, sort_order; lesson module_id, lesson_type, content_file_id, duration_minutesModule → lesson
lms_assessment / lms_questionpass_percent, max_attempts; question prompt, options, answer_keyanswer_key is never sent to learners
lms_assignment_rulecourse_id, applicability, trigger (ON_JOIN, ON_JOB_CHANGE, RECURRING), due_days
lms_enrollmentcourse_id, employee_id, source, due_date, status, score_percent, completed_at
lms_progressenrollment_id, lesson_id UNIQUE pair, status
lms_attemptenrollment_id, attempt_no, score_percent, passed
lms_certificateenrollment_id UNIQUE, certificate_no UNIQUE, file_id, issued_atPublic verification by number
lms_badge / lms_badge_awardbadge name, criteria; award badge_id, employee_id, awarded_atLeaderboards

Control-plane database​

Separate database, no RLS by tenant (platform staff only), no module prefix. Standard columns apply except tenant_id.

tenant​

ColumnTypeConstraintsNotes
slugtextUNIQUE, CHECK lowercase letters, digits and hyphens, 3–31 charsImmutable
company_codetextUNIQUEHuman-friendly mobile code
legal_name, display_nametext
statustextCHECKPROVISIONING, TRIAL, ACTIVE, PAST_DUE, SUSPENDED, CHURNED, DELETED
cell_iduuidFK cellRouting
regiontextdefault ap-south-1
owner_emailcitextInvite target
trial_ends_on, activated_at, suspended_at, delete_afterdate/timestamptzLifecycle
legal_holdboolBlocks deletion

tenant_domain / tenant_lifecycle_event / slug_alias​

ColumnTypeConstraintsNotes
domain.hostnametextUNIQUECustom domain (Enterprise)
domain.verification_token, status, verified_at, cert_statustext, text, timestamptz, textPENDING_DNS, VERIFIED, ACTIVE, FAILED
lifecycle.from_status, to_status, reason, actor, occurred_attext…append-only
slug_alias.old_slugtextUNIQUERedirects after a rename

cell​

ColumnTypeConstraintsNotes
codetextUNIQUEp1, d-acme
typetextCHECKPOOLED, DEDICATED_DB, DEDICATED_STACK
regiontext
api_base_urltext
db_secret_reftextSecrets Manager ARN; never the DSN itself
app_versiontextCurrent release
wave_iduuidFK rollout_wave
statustextCHECKACTIVE, DRAINING, MAINTENANCE, RETIRED
capacityjsonbLatest tenant count, employee count, DB size, CPU peak
maintenance_windowtextFor dedicated cells

plan / plan_entitlement / addon​

ColumnTypeConstraintsNotes
plan.codetextUNIQUELITE, STANDARD, PROFESSIONAL, ENTERPRISE
plan.pepm_paise, minimum_monthly_paisebigintCommercials pending (ADR-013)
plan.max_employeesintLite = 50
entitlement.feature_keytextUNIQUE (plan_id, feature_key)module.clm, sso.oidc, api.public, limit.storage_gb
entitlement.limit_valuebigintNull = boolean feature
addon.code, metric, unit_price_paisetext, text, bigintFFM per tracked user, FACE per enrolled employee, WHATSAPP per message

tenant_subscription / subscription_addon / entitlement_override​

ColumnTypeConstraintsNotes
subscription.tenant_id, plan_iduuidone active per tenant
subscription.billing_cycletextCHECKMONTHLY, ANNUAL
subscription.razorpay_subscription_idtextUNIQUE
subscription.statustextCHECKTRIALING, ACTIVE, PAST_DUE, CANCELLED
subscription.current_period_start, current_period_enddate
subscription_addon.addon_id, quantityuuid, int
override.feature_key, limit_value, valid_to, reason, approved_bytext, bigint, date, text, uuidAudited

usage_daily / invoice​

ColumnTypeConstraintsNotes
usage.tenant_id, usage_date, metricuuid, date, textUNIQUE tripleACTIVE_EMPLOYEES, TRACKED_USERS, SMS, WHATSAPP, STORAGE_MB, FACE_ENROLLED
usage.valuebigint
invoice.numbertextUNIQUEGST series
invoice.period_start, period_end, subtotal_paise, gst_paise, total_paisedate, date, bigint…
invoice.statustextCHECKDRAFT, ISSUED, PAID, OVERDUE, VOID
invoice.linesjsonbPlan, add-ons, metered usage

provisioning_run / provisioning_step​

ColumnTypeConstraintsNotes
run.tenant_iduuidFK
run.idempotency_keytextUNIQUEFrom the Idempotency-Key header
run.statustextCHECKPENDING, RUNNING, SUCCEEDED, FAILED, COMPENSATED
step.step_keytextUNIQUE (run_id, step_key)VALIDATE, SELECT_CELL, CREATE_TENANT_ROW, SEED_REFERENCE_DATA, SEED_ROLES, SEED_POLICIES, CREATE_OWNER_INVITE, CONFIGURE_DOMAIN, SEND_WELCOME
step.attempt, status, error, finished_atint, text, jsonb, timestamptzResumable from the failed step

feature_flag / flag_rule​

ColumnTypeConstraintsNotes
flag.keytextUNIQUEpay.new-run-ui, kill.face-verification
flag.type, default_valuetext, jsonbBOOLEAN, STRING, NUMBER, JSON
flag.is_kill_switch, owner, expires_onbool, text, dateStale flags are reported
rule.target_typetextCHECKTENANT, CELL, PLAN, PERCENTAGE
rule.target_id, value, prioritytext, jsonb, int

release / rollout_wave / cell_rollout​

ColumnTypeConstraintsNotes
release.git_shatextUNIQUE
release.version, migration_ids, notestext, jsonb, text
wave.wave_nointUNIQUE0 internal/canary, 1 pooled, 2 dedicated
wave.soak_hoursint24 or 48 (ADR-010)
cell_rollout.cell_id, release_iduuidUNIQUE pair
cell_rollout.statustextCHECKPENDING, MIGRATING, DEPLOYED, HALTED, ROLLED_BACK
cell_rollout.migrated_at, deployed_at, slo_checktimestamptz, timestamptz, jsonb

platform_user / support_access_grant / audit_event​

ColumnTypeConstraintsNotes
platform_user.emailcitextUNIQUEStaff only; MFA mandatory
platform_user.roletextCHECKplatform_admin, support_engineer, billing_admin, release_manager
grant.tenant_id, platform_user_iduuidFK
grant.reason, ticket_reftextNOT NULL
grant.access_modetextCHECKREAD_ONLY, READ_WRITE
grant.expires_attimestamptz≤ 8 h after start
grant.consented_by, consented_atuuid, timestamptzTenant owner, when the plan requires consent
grant.statustextCHECKREQUESTED, ACTIVE, EXPIRED, REVOKED, DENIED
audit_eventas sys_audit_eventappend-onlyControl-plane actions

statutory_pack / statutory_pack_item​

ColumnTypeConstraintsNotes
pack.versiontextUNIQUE
pack.valid_from, status, published_at, published_bydate, text, timestamptz, uuidDRAFT, REVIEWED, PUBLISHED
pack.change_logtextShown to payroll managers
item.scheme, state_code, ratestext, text, jsonbCopied into each cell's pay_statutory_rate with the pack version. All values are examples to verify.