Appearance
Changelog
What changed in Verity, newest first.
Entries describe what an operator or administrator will notice. Where a change alters what Verity claims — rather than what it looks like — that is called out, because those are the changes worth reading twice.
12 August 2026
Elm refused to run over two values that were never yours to set
Elm's usage code and operator id are fixed by the Yakeen contract. Neither is issued with the Elm credentials and neither appears in any provider portal — but both were required environment variables, so a deployment holding every credential Elm gave us was refused on every call with "ELM_USAGE_CODE is not set". The natural response, copying the placeholder out of .env.example, is how staging came to send the literal string replace-me to Yakeen and get back "replace-me is not valid usage-code": a request error for what was really a configuration error.
Both now default in code to the contract values, so a deployment that sets neither works. A placeholder base URL is likewise treated as unset rather than sent to be rejected as a malformed address.
Provider settings, and where each value comes from
Settings → Providers now holds the usage code and operator id per account, for the case where an account genuinely queries under a different registration — and so the values can be read back without shell access to a container.
The screen states which of three sources each value came from: set here, from the environment variable, or the contract default. That label matters as much as the fields, because a blank field on a working provider looks exactly like a blank field on a broken one. It reads the answer from the same resolver the outgoing request reads it from, so the screen cannot state a value that is not the one being sent.
Clearing a field returns to the default rather than sending an empty header. Changes are audited with the before and after values — neither is a secret, and the row itself only holds the current answer.
Its own permission pair, provider_configuration.view and .manage, granted by default to whoever already holds api_key.manage. Managing them needs authority in every country: what they declare applies to every request the account makes.
See Provider settings.
The person page said "DOB on file" for a date the identity check could not use
What Verity claimed changed. The person page decided whether a date of birth was on file by reading the Gregorian column. Yakeen matches Saudi citizens on a Hijri date, so for a citizen the page was answering the opposite of the question the provider would be asked: a correct Hijri date read as "DOB missing" beside a live identity button, and a Gregorian date read as "DOB on file" beside the same button dead with "Needs date of birth".
Both readings are now taken from the same predicate the check runs on. A date in the wrong calendar gets its own state — the value is shown, and the page says it cannot be used and which calendar is wanted — because telling an operator a date is "missing" when one is sitting in the field sends them to retype it unchanged. The field to correct it is now offered in that case too; previously the record was stuck with an unusable value.
The identity grade is gone
The header carried Strong / Moderate / Thin identity. It read the same Gregorian column, so it returned "Moderate identity" for every person in the database — a confident-sounding band that could not vary and that no evidence wrote. Its two inputs are already on the header as facts: whether there is a hard identifier, and whether a usable date of birth is on file. A reader can weigh those; a grade asked them to trust an arithmetic nobody could inspect.
The person page now opens with what has been checked
Previously an operator had to read seven sections to learn whether anyone had looked at a person, with the two Elm reads at the very bottom. The page now opens with Checks on this person: every person-scoped check, its outcome, and where there is none, why — with the unread ones grouped by the cause they share, under the same words the entity page uses. Not assessed is not the same as clear. A person with nothing run reads as an empty file rather than a quiet one.
Alongside it:
- Identity puts what the file holds beside what the government record returned, in one table. Before, the claim was at the top of the page and the verification of it five sections below, so the comparison that is the entire point of an identity check could not be made without scrolling. No automatic per-field match verdict: names arrive transliterated and dates in either calendar, and a string comparison would report mismatches that are only spelling.
- Registered address lists the addresses the register returned. It used to report only how many.
- Check history is folded away at the end. It is the plumbing behind the verdicts, and it used to sit above the findings it produced.
- An expiring ID is shown; the page carried it nowhere before.
Whether a check ran is visible to anyone who can see the person, on the same footing as the entity page's party chips. What a provider said when a run failed still needs provider_fetch_run.view.
See The person workspace.
11 August 2026
Screening a merchant another system already onboarded
Focal's screening endpoints onboard a customer; they are not a repeatable query. A merchant already held by the shared Focal tenant — commonly onboarded by another Moyasar system — was refused with a conflict, and Verity recorded a failed check for a merchant that had in fact been screened.
Verity now reads the screening Focal already holds instead of giving up. The evidence records that the result was retrieved rather than screened now, alongside the date Focal ran it, so a result from months ago is never presented as a check you just ran.
If the read also fails, the check still fails. Nothing is claimed either way.
Working in one country
A team member can now be confined to a single country. Their entity list, review queue and provider evidence are filtered to it, and a merchant in another country is refused.
Account-wide settings still need authority in every country, with one deliberate exception: a country-scoped administrator can tune their own country's defaults.
See Team and permissions.
Eight new roles
The role catalogue now separates preparing a review from approving one. No role except Operations Admin holds both — one person prepares a file, another signs it off.
Onboarding Officer, KYB Analyst, Compliance Officer, AML Officer (MLRO), Compliance Policy Admin, Compliance Auditor and Account Administrator join the three that existed. Nobody is moved automatically: existing members keep exactly the access they had until an administrator moves them.
Review Analyst is superseded but kept, so its current holders are unaffected.
Individual permissions
A member can hold a permission their role does not carry, for a real exception — the analyst covering the MLRO's leave. Each one records where it applies, why, who granted it, and when it expires.
You cannot grant what you do not hold, and two permissions are never grantable this way at all.
What a member can decide
A member's page now answers the question directly — can this person approve, reject, escalate, adjudicate, bar, manage the team — and names the role or grant carrying each one, rather than leaving you to read twenty-eight permission rows.
Clearer configuration errors
A provider credential left as replace-me used to be sent to the provider, whose rejection is what you saw. Placeholders now read as missing configuration, so the error names the setting instead of quoting a provider's error code.
10 August 2026
Screening lists are configured, not assumed
Screening now runs against the lists you choose, under Settings → Screening lists.
This is the significant one. A screening request that names no lists returns an empty match set that is indistinguishable from a clean subject. Verity previously sent no list selection at all.
A subject type with no list behind it now fails the check rather than returning a quiet clean result, the sanctions gate reads not assessed, and approval stays blocked. Configure both individuals and organizations before running screening.
An entity has a history
The entity page's Recent activity shows what has actually happened to a merchant — details edited, documents uploaded, checks run, provider updates, and the decisions taken on its reviews.
It was empty on every entity before this, because it asked for a kind of record nothing ever wrote.
The heading links to the full history, which needs entity.activity.view.
Standing bars
Merchants and people can be barred from future acceptance, from the entity or person page as well as from Settings → Standing bars. A strong identifier — national ID, registration number, IBAN — blocks approval outright; a name only warns, because names collide.
The form is folded behind a control on the entity and person pages: across a thousand merchants, perhaps one is barred.
Invitations last a day
An invitation link is valid for one day rather than the fifteen minutes it inherited from password resets, and an expired one can be re-sent from the team screen without removing and re-inviting the member.
IBAN verification reports a verdict
The IBAN check completed without saying whether the account checked out — it read fields the provider does not send. It now reads the provider's actual response, and the check row shows verified or not verified. An unrecognised status stays blank rather than guessing.
Website scan
Runs in the background rather than blocking, and no longer fails on pages with non-ASCII content — which included most Arabic sites.
Uploaded documents open
A document uploaded to an entity can be opened from the entity page. Only types a browser renders safely open inline; everything else downloads.
Arabic
The interface is available in Arabic, with a direction-aware layout. Translation is in progress: the app bar, entities list and party cards are done; the entity page, review cockpit and settings are still English.
Earlier
- Entities API pagination, and a sort control on the entities list
- A screen-by-screen guide with real screenshots, and the walkthrough
- Personal data filtered from application logs