LendEasy/DocsLMS + Servicing·v1
Start integrating
Guides›Overview›Security model

Security model

How LendEasy layers tenancy, exact-permission authorization, tokenized and masked data, governed change, and tamper-evident evidence into one security posture you can verify surface by surface.

LendEasy’s security posture is not one product feature — it is the same five mechanisms applied at every surface of the platform: isolate the tenant, demand the exact permission, never hold raw secrets, freeze every consequential change behind a second decision, and keep records that prove what happened. This page is the rollup; each section links to the deep-dive guide where the mechanism is specified.

Nothing crosses between tenants or environments

Sandbox and Production are fully separate — no shared credentials, IDs, idempotency records, customer data, provider configuration, signing secrets, or generated artifacts — and a token issued for one environment is rejected by the other. Within an environment, every call names its tenant with the LendEasy-Tenant header — the header selects, the token authorizes — and a resource from another tenant behaves as unavailable. Sandbox preserves the implemented Production contract while simulating only external effects, so controls are exercised before promotion rather than discovered after it.

See Environments & base URLs.

Eight layers, and any one can deny

Machine access uses OAuth 2.0 client credentials, each bound to one tenant and one environment, with every workload given its own least-privilege client — so revoking the credential behind one integration at three in the morning does not take the others down with it. Scopes establish the broad surface; the decisive check is the exact named permission on every endpoint — a token can carry lending:write and still lack APPROVE_LMS_FUNDING. Authorization is evaluated in layers — environment-valid token, tenant isolation, scope, exact permission, resource visibility, field sensitivity, case context where required, and maker-checker — and failure at any layer denies it. A broader scope never fills a missing permission, and human servicing mutations must additionally carry a valid open-case reference that establishes the actor’s relationship to the work.

See Authentication and Access control & maker-checker.

Tokenized instruments, masked identifiers, audited sensitive reads

A filter is a list of places a value has to be stripped from, and that list is only ever as complete as the last person who added a log line. So the values are kept where no filter is needed:

  • Tokenized instruments. Payment instruments accept a provider vault token — never a raw account or card number — so no route can leak one; ordinary reads return masked metadata only. See Payment instruments.
  • Masked identifiers. Government identifiers are supplied once at write time, normalized, and never echoed back — not in command records, history events, or logs. Ordinary reads return the type, mask, and lifecycle state only. See Customer identifiers.
  • Audited sensitive reads. Complete values live behind dedicated /sensitive routes that require the ordinary read permission and an additional _SENSITIVE permission. Every sensitive read is audited and served no-store, and exact-match lookup answers with masked summaries without revealing whether hidden matches exist. See Access control.
  • Scan-gated documents. Uploaded document bytes are not downloadable until a malware scan returns clean; rejected content is quarantined and deleted while the record remains as evidence. Downloads re-verify the stored checksum so corruption is detected rather than delivered. See Documents.
  • Per-form derived permissions. Publishing a form definition auto-registers READ_LMS_FORM_<KEY>, WRITE_LMS_FORM_<KEY>, and DELETE_LMS_FORM_<KEY> from the form key, so each form’s entries are grantable independently rather than through one blanket forms permission. See Forms.

The maker can never be the checker

Consequential change moves through governed commands with second-person control. Native maker-checker parks a flagged command instead of executing it — payload frozen in the checker inbox — and a different actor decides. The same separation recurs in dedicated flows such as funding approval and reschedule decisions. Every governed command execution writes a governance record capturing the permission code, route, actor class, and case or system context. Records are never edited: corrections and supersessions add records rather than editing originals, so the version an actor decided on is still readable beside the correction that replaced it and what did we know at the time stays an answerable question. Reconciliation repairs go through the owning domain against the authoritative source, never by editing a read model to match an expectation.

See Access control & maker-checker and Reconciliation & drift.

Causation is linked by ID and hash

The evidence graph links source signals, cases, fact sets, rule versions, decisions, approvals, executions, acknowledgements, and reconciliation outcomes through explicit IDs and hashes — temporal proximity is never treated as causation. Decision records name the exact facts, sources, freshness, and rule versions behind each outcome, and approvals preserve actor, decision, reason, request hash, and separation-of-duties result. The record set is tamper-evident: records carry content digests, and evidence packages include a manifest of record IDs, versions, artifact SHA-256 values, and a package digest, so any changed or missing item breaks verification. Audited evidence exports reconstruct the causal record per case or per customer as point-in-time examination bundles, without silently including restricted documents the requesting actor cannot read.

See Evidence graph.

AI works under the same actor discipline

Grounded outputs are reviewed through a dedicated route where a human accepts, edits, rejects, ignores, or escalates — the original output stays immutable beside the reviewed result, and reviewers see cited facts and freshness rather than only polished prose. A suppression control stops AI work by scope — tenant, agent profile, model version, queue, case type, channel, tool, or action — with dispatch checking suppression before starting and active sessions rechecking before every tool call, so the switch takes effect without waiting for sessions to drain. The reviewer permission and the suppression permission are deliberately distinct: judging one drafted reply and switching off an entire agent profile mid-incident are different acts with different blast radii, and the person trusted with the first is not automatically the person trusted with the second. The AI session and its reviewer are always distinct actors.

See How agents are governed.

The exact runtime surface behind these mechanisms is listed on API availability — the single source of truth for what is callable in the current build.
Unified search across guides, recipes & the API referenceEsc