Hawk Ai Log in

Feature catalogue

All 500 features with their real status: built, partial or not started, each with the file you can check it against.

Last updated
500features in the catalogue
457 built
9 partial
34 not started
307 core · 153 expected · 40 extra

Counted with no provider configured — the strictest reading. This page checks the running deployment when it loads and raises anything whose provider answers.

This is the whole product written down: what is built, what is half built, and what is not started. Three rules keep it usable. Built means a reader can find it in the repository, and the last column says where. Anything that depends on a provider, a credential or a contract is shown one step lower until the provider actually answers — so this page describes this deployment, not the ambition. Not started is written plainly, with the reason, because a catalogue that shows 500 of 500 complete is a catalogue nobody believes.

The catalogue is maintained in English: the entries are engineering statements tied to file names, and a translated copy would drift from the code within a release. The rest of Hawk Ai, including everything an applicant sees, is available in fourteen languages. The same data is at GET /v2/features.

Applicant intake 40/40

IDFeatureStatusPriorityWhere to check it · what it needs
intake.001Hosted verification flow on a per-applicant linkBuiltCorepublic/verify.html · POST /v2/verification-sessions
intake.002Verification link is single-useBuiltCoreserver/api.js — verify/submit rejects a used session
intake.003Verification link expires (7 days)BuiltCoreverification_sessions.expires_at
intake.004Submission requires a valid session tokenBuiltCoreserver/api.js — 401 without one
intake.005Applicant consent captured before any checkBuiltCoreconsents table · step 1 of the flow
intake.006Consent text stored verbatim with the recordBuiltCoreconsents.text
intake.007Consent records the IP it was given fromBuiltCoreconsents.ip
intake.008Step-by-step progress indicatorBuiltCorepublic/verify.html — 8-step stepper
intake.009Resume progress on refreshBuiltCorein-page state, plus the encrypted server-side draft on a live session
intake.010Mobile-first layoutBuiltCorepublic/assets/css/hawkai.css
intake.011Flow is white-labelled with the client nameBuiltCoreGET /v2/verify/session/:token · data-client-tpl
intake.012Flow adopts the client brand colourBuiltExpectedtenants.color → --client custom property
intake.013Client logo on the flowBuiltExpectedPOST /v2/tenant/branding/logo — 200 KB cap, and an SVG carrying script is refused rather than sanitised
intake.014Flow available in 14 languagesBuiltCorepublic/assets/i18n · 3,100 keys
intake.015Right-to-left layout for ArabicBuiltCorepublic/assets/css/rtl.css
intake.016Language chosen per linkBuiltCoreverification_sessions.locale
intake.017Applicant can switch language mid-flowBuiltExpectedi18n switcher, no reload, route preserved
intake.018Client reference carried through (external_id)BuiltCoreverification_sessions.external_id → applicant
intake.019Redirect back to the client on completionBuiltExpectedthe flow navigates to the link’s redirect_url with the outcome; http(s) only, so it cannot be turned into an open redirect
intake.020Applicant told what happens next, never the internal signalsBuiltCoreserver/api.js — message, no blocked_reasons
intake.021Honest failure when the server refuses a submissionBuiltCorepublic/verify.html — renders a refusal, not a fake approval
intake.022Demo controls hidden on a live sessionBuiltCoredisplay:none !important on every data-demo-only affordance when a session is present
intake.023Outcome cannot be changed client-side on a live sessionBuiltCoresetOutcome pinned; the server decides
intake.024Rate limit on submissionsBuiltExpected20/min per IP
intake.025Server-side applicant creation via APIBuiltCorePOST /v2/applicants
intake.026Bulk applicant importBuiltExpectedPOST /v2/applicants/import — CSV, validated first, and it says which rows it refused
intake.027Re-verification of an existing applicantBuiltExpectedPOST /v2/applicants/:id/recheck
intake.028Applicant can save and resume later from a linkBuiltExtrathe draft is encrypted against the session; images are deliberately not kept
intake.029Country of document chosen by the applicantBuiltExpectedevery ISO 3166-1 code, named from the reader’s own CLDR data
intake.030Document type chosen by the applicantBuiltExpectedpassport / ID card / licence / residence permit
intake.031Address and personal details captureBuiltCoredetails step
intake.032Employer and job title captureBuiltExpecteddetails step — used for the footprint cross-check
intake.033Accessibility: keyboard-navigable flowBuiltExpectedfocus management between steps
intake.034Accessibility: visible focus and ARIA labelsBuiltExpectedhawkai.css :focus-visible · aria-label on controls
intake.035Accessibility: WCAG AA contrast across both themesBuiltExtraaudited — 7 remaining are third-party brand colours
intake.036Light and dark themes on the flowBuiltExpectedA.theme, applied before first paint
intake.037Theme follows the operating system and updates liveBuiltExtraprefers-color-scheme listener
intake.038Applicant sees which checks ranBuiltExpectedchecks_ran in the submission response
intake.039Privacy notice linked from the flowBuiltCorecontent/privacy.md → /privacy
intake.040Retention explained to the applicant in their languageBuiltExpectedboth clocks stated, 14 languages

Identity documents 24/30

IDFeatureStatusPriorityWhere to check it · what it needs
doc.001Document image capture in the browserBuiltCoregetUserMedia on a live session, downscaled to 1600px and uploaded; a file input when the camera is refused or absent
doc.002Front and back capture for two-sided documentsBuiltCorethe back is asked for only when the chosen document type has one
doc.003Document images encrypted at restBuiltCoreserver/crypto.js AES-256-GCM · documents.data_enc
doc.004Document upload via APIBuiltCorePOST /v2/applicants/:id/documents
doc.005Upload size limit enforcedBuiltCore8 MB per image
doc.006Base64 payload validated before storingBuiltCorerejects anything that does not decode
doc.007MRZ parsingBuiltCoreserver/adapters/index.js parseMrz
doc.008MRZ check-digit arithmetic verified ourselvesBuiltCoremrzCheckDigit — not a model, arithmetic
doc.009MRZ document number, DOB and expiry extractedBuiltCoreparseMrz fields
doc.010Expired document detectedBuiltCoreexpiry compared against the decision date
doc.011Age derived from the document and checked against a minimumBuiltCoreserver/engine.js ageFrom · UNDERAGE block
doc.012Document authenticity (print, fonts, holograms)Not startedCoreneeds a document-authenticity provider
doc.013Tamper and alteration detectionNot startedCoreneeds a document-authenticity provider
doc.014Tampered document blocks approval, unconditionallyBuiltCoreserver/engine.js HARD_BLOCKS
doc.015OCR of the visual inspection zoneNot startedCoreneeds a document-authenticity provider
doc.016Document type coverage (passport, ID, licence, permit)PartialExpectedneeds a document-authenticity provider
doc.017NFC chip read for ePassportsNot startedExpectedneeds WebNFC plus a provider that verifies the SOD signature
doc.018Glare and blur guidance during captureBuiltExpectedcapture hints in the flow
doc.019Retake prompt on a failed captureBuiltExpecteddocument step
doc.020Document images deleted on the retention clockBuiltCoreserver/retention.js — 90 days after the decision
doc.021Erased image returns 410 with the reasonBuiltCoreGET /v2/documents/:id
doc.022Document hash kept after the image is erasedBuiltCorethe row survives; data_enc is nulled
doc.023Reviewer can view the document in the consoleBuiltExpectedpublic/admin.html document panel
doc.024Every view of a document is auditedBuiltExpectedserver/audit.js category access
doc.025Side-by-side document and selfie comparison for the reviewerBuiltExtraadmin applicant detail
doc.026Document country vs declared nationality cross-checkBuiltExpectedengine signal
doc.027Document number duplicate detection across applicantsBuiltExpecteda per-tenant keyed hash, so the comparison works and the number is not stored
doc.028Proof-of-address document captureBuiltExtraasked for in the flow when the client sets requireProofOfAddress, and the submit button waits for it
doc.029Sanctioned or high-risk issuing country flaggedBuiltExpectedcountry risk signal in the engine
doc.030Document template version recorded for auditNot startedExtraneeds a document-authenticity provider

Biometrics and liveness 10/15

IDFeatureStatusPriorityWhere to check it · what it needs
bio.001Selfie capture in the browserBuiltCorethe front camera on a live session, uploaded against the verification link
bio.002Selfie encrypted at restBuiltCoreAES-256-GCM, same key policy as documents
bio.003Face match: selfie against the document portraitNot startedCoreneeds a face-match and liveness provider
bio.004Passive livenessNot startedCoreneeds a face-match and liveness provider
bio.005Active liveness challengeNot startedExpectedneeds a face-match and liveness provider
bio.006Deepfake and injection-attack detectionNot startedCoreneeds a face-match and liveness provider
bio.007A liveness check that did not run blocks approvalBuiltCoreCHECK_DID_NOT_RUN — silence is never a pass
bio.008Biometric data treated as special categoryBuiltCoreprivacy notice + DPA; explicit consent basis
bio.009Selfie deleted on the retention clockBuiltCoreserver/retention.js
bio.010Face match score shown to the reviewerPartialExpectedneeds a face-match and liveness provider
bio.011Attempt count recordedBuiltExpectedapplicant timeline
bio.012Camera permission denial handled gracefullyBuiltExtrafile upload fallback
bio.013Front camera preferred on mobileBuiltExtrafacingMode user
bio.014Selfie never shared with third parties beyond the providerBuiltExpectedstated in the privacy notice; no other egress
bio.015Biometric consent can be withdrawnBuiltExtrawithdraw flow in My Hawk Ai ID

Screening 33/35

IDFeatureStatusPriorityWhere to check it · what it needs
scr.001Sanctions screening against the official listsBuiltCoretools/load-sanctions.js · 26,103 designations
scr.002OFAC Specially Designated Nationals loadedBuiltCoreUS Treasury sdn.csv — ~19,400
scr.003OFAC Consolidated (non-SDN) loadedBuiltCoreUS Treasury cons_prim.csv
scr.004EU Consolidated financial sanctions list loadedBuiltCoreEuropean Commission FSF
scr.005Aliases screened as first-class namesBuiltCorealt.csv and EU NameAlias rows — 67k searchable
scr.006Lists refreshed automaticallyBuiltCoreserver.js — daily, plus 20s after a boot with none
scr.007List age reported and flagged stale past 7 daysBuiltCoreGET /v2/screening/lists
scr.008Manual refresh (platform admin)BuiltExpectedPOST /v2/screening/refresh
scr.009Provenance recorded per list (authority, URL, date)BuiltCorescreening_lists.source and .version
scr.010Fuzzy name matching tolerant of transliterationBuiltCoretoken-level Jaro-Winkler
scr.011Name order independenceBuiltCoregreedy token pairing — "Al-Tikriti, Saddam" = "Saddam Al-Tikriti"
scr.012Diacritics and case normalisedBuiltCoreNFKD, combining marks stripped
scr.013Non-Latin scripts matched, not discardedBuiltCorenameNorm keeps \p{L} — the old version emptied them
scr.014Both sides of a name must be covered to scoreBuiltCoreharmonic mean of the two coverages
scr.015Date of birth corroboration promotes or demotes a candidateBuiltCoredob_match ±ranking
scr.016Match score exposed for triageBuiltCorehits[].score
scr.017Precision and recall measured, not assumedBuiltCoretools/test/screening-precision.js — 6/6 recall, 9% referral
scr.018Confirmed sanctions match blocks approval, unconditionallyBuiltCoreSANCTIONS_MATCH in HARD_BLOCKS
scr.019Reviewer confirms or dismisses each hitBuiltCorePOST /v2/applicants/:id/screening/:index
scr.020Dismissing a hit requires a written reasonBuiltCorerefuses without one — it is the record of why
scr.021Hit resolution is auditedBuiltCoreserver/audit.js
scr.022Which list a hit came from is shownBuiltExpectedhits[].list
scr.023Designation reference shown for verification against the sourceBuiltExpectedhits[].ref
scr.024Entity vs individual distinguishedBuiltExpectedentries.kind
scr.025PEP screeningNot startedCoreneeds a commercial PEP / adverse-media data set
scr.026Adverse-media screeningNot startedCoreneeds a commercial PEP / adverse-media data set
scr.027Readiness separates sanctions from PEP/adverse mediaBuiltCore/readyz sanctions and pep_adverse are distinct items
scr.028Ongoing monitoring: re-screen as lists changeBuiltCoreserver/monitoring.js — runs after every list refresh, alerts only on hits that are new
scr.029Operator-supplied internal blocklistBuiltExpectedPUT /v2/screening/internal — tagged to the tenant, and the matcher refuses to score it for anyone else
scr.030Country and programme of designation shownBuiltExtraentries.country · programme captured at load
scr.031Screening runs on a vendor instead, if configuredBuiltExpectedSCREENING_PROVIDER_URL takes precedence
scr.032Screening result recorded on the applicantBuiltExpectedapplicants.screening
scr.033False-positive rate guarded by a test that fails the buildBuiltExtratools/test/screening-precision.js — fails above 15%
scr.034Matcher index memory boundedBuiltExtrafirst-character blocking — 51 MB, was 211 MB
scr.035Screening latency boundedBuiltExtrameasured 31 ms per check

Signals 12/18

IDFeatureStatusPriorityWhere to check it · what it needs
sig.001IP address recorded with each submissionBuiltCoreapplicants.ip
sig.002User agent, browser and OS recordedBuiltCoreapplicants.ua · device
sig.003Velocity: repeat submissions from one addressBuiltCoreserver/adapters device signals
sig.004Repeat device fingerprint across applicantsBuiltCoredevice signal
sig.005Automated client and emulator detection (our own signals)BuiltCoredevice adapter — local mode
sig.006Typing cadence and paste-count as a scripted-input signalBuiltExpectedcollected in the flow, scored by the engine
sig.007Timezone vs declared country mismatchBuiltExpecteddevice signal
sig.008E-mail age and disposabilityNot startedCoreneeds an e-mail/phone intelligence provider
sig.009Breach appearance for the e-mailNot startedCoreneeds an e-mail/phone intelligence provider
sig.010Phone line type (VoIP, mobile, landline)Not startedCoreneeds an e-mail/phone intelligence provider
sig.011Carrier and SIM-swap recencyNot startedExpectedneeds an e-mail/phone intelligence provider
sig.012VPN, proxy and hosting-provider detectionNot startedCoreneeds an e-mail/phone intelligence provider
sig.013An intelligence check that did not run blocks approvalBuiltCoreCHECK_DID_NOT_RUN
sig.014Signals visible to the reviewer with provenanceBuiltExpectedadmin applicant detail — each signal names its source
sig.015Signals shown to the applicant on request (developer view)BuiltExpectedverify.html dev drawer, demo only
sig.016Signal weights configurable per clientBuiltExtratenants.settings → engine.rulesFor
sig.017Device signals never used to identify across clientsBuiltExpectedfingerprints are tenant-scoped
sig.018Geo-IP city and countryNot startedExtraneeds an e-mail/phone intelligence provider

Digital footprint 10/15

IDFeatureStatusPriorityWhere to check it · what it needs
fp.001Footprint check runs only with explicit consentBuiltCoreconsent step gates it; consents.kind = footprint
fp.002Public data only — never posts, follows or messagesBuiltCorestated in the privacy notice; adapter is read-only
fp.003Candidate profiles resolved from name, e-mail, phone and handlesNot startedCoreneeds a digital-footprint provider
fp.004Applicant confirms which profiles are theirsBuiltCorefootprint step in the flow
fp.005Account age as a signalNot startedCoreneeds a digital-footprint provider
fp.006Profile photo similarity to the verified selfieNot startedCoreneeds a digital-footprint provider
fp.007Declared employer vs public profile employerBuiltExpectedengine cross-check when data is present
fp.008Stock-photo avatar detectionNot startedExpectedneeds a digital-footprint provider
fp.009Absence of a footprint never rejects anybodyBuiltCoreengine — stated on the marketing page too
fp.010Consent withdrawal stops the check and deletes lookupsBuiltCoreMy Hawk Ai ID withdraw flow
fp.011Networks shown as lettermark tiles, never third-party logosBuiltExpectedA.netTile — no borrowed brand marks
fp.012Per-network result with a match scorePartialExpectedneeds a digital-footprint provider
fp.013Footprint flags explained in plain languageBuiltExtraflagLabel in landing.js and the admin detail
fp.014Footprint disabled per clientBuiltExtratenants.settings
fp.015Footprint result recorded on the applicantBuiltExpectedapplicants.social

Decision engine 30/30

IDFeatureStatusPriorityWhere to check it · what it needs
eng.001Risk score from weighted signalsBuiltCoreserver/engine.js evaluate
eng.002Three outcomes: approved, review, rejectedBuiltCoreserver/applicants.js
eng.003Referral is not rejectionBuiltCorereview is a distinct state with its own queue
eng.004Four blocks no setting can disableBuiltCoreHARD_BLOCKS — sanctions, tamper, underage, check-did-not-run
eng.005A check that did not run counts as not passedBuiltCorethe single most important behaviour in the system
eng.006Blocks are verdicts; only their mandatoriness is configurableBuiltCoreclosed a hole where requireScreening:false removed the block
eng.007Blocked approval refused at the API with 409BuiltCorePOST /v2/applicants/:id/decision
eng.008Refusal is actionable — it says what would have to changeBuiltCoreremedy[] per block code
eng.009Blocks grouped by code, with the specifics underneathBuiltCorethree unconfigured providers no longer repeat one sentence
eng.010A refused approval reverts on screenBuiltCorepublic/assets/js/live.js wrapDecide
eng.011Per-client scoring thresholdsBuiltCoreengine.rulesFor(tenant.settings)
eng.012Per-client minimum ageBuiltCorerules.minimumAge
eng.013Per-client required-check setBuiltExpectedrules.require*
eng.014Auto-approve thresholdBuiltExpectedrules.autoApproveBelow
eng.015Auto-reject thresholdBuiltExpectedrules.autoRejectAbove
eng.016Every signal contributing to a score is itemisedBuiltCoresignals[] with points and label
eng.017Decision recorded with its reasoningBuiltCoredecisions table
eng.018Decision immutable once writtenBuiltCoredecisions rows are inserted, never updated
eng.019Rules catalogue with per-rule enable and hit countsBuiltExpectedGET /v2/tenant/rules
eng.020Rule changes audited with who and whenBuiltExpectedaudit category config
eng.021Rule simulation against historical applicantsBuiltExpectedPOST /v2/tenant/rules/simulate — replays stored check results, writes nothing
eng.022Score explanation ordered by contributionBuiltExtrasignals sorted by points
eng.023Effective rules returned with the tenant configBuiltExpectedGET /v2/tenant → effectiveRules
eng.024Four-eyes review for high-risk approvalsBuiltExpectedenforced in the one decision gate — an endorsement from a different person is required; off by default, because on a one-reviewer client it would deadlock
eng.025Decision latency measured and reportedBuiltExtraanalytics avgTime
eng.026Manual override with a recorded reasonBuiltExpecteddecision reason is required for a manual outcome
eng.027Age check uses the document date of birthBuiltCoreengine ageFrom
eng.028Country risk tiersBuiltExpectedengine country signal
eng.029Rule packs by industryBuiltExtraconsole flow templates
eng.030Engine behaviour documented for a regulatorBuiltExtracontent/docs.md — what a decision means

Review and cases 23/25

IDFeatureStatusPriorityWhere to check it · what it needs
rev.001Applicant queue with status filtersBuiltCorepublic/admin.html · GET /v2/applicants
rev.002Applicant detail with every signal and its evidenceBuiltCoreadmin applicant detail
rev.003Approve, reject, request resubmission, escalateBuiltCorePOST /v2/applicants/:id/decision
rev.004Reviewer identity recorded on the decisionBuiltCoreapplicants.reviewer
rev.005Notes on an applicantBuiltCorePOST /v2/applicants/:id/notes
rev.006Timeline of everything that happenedBuiltCoreapplicants.timeline
rev.007Reading an applicant record is itself auditedBuiltCoreaudit category access
rev.008Cases for anything needing investigationBuiltCorecases table · POST /v2/cases
rev.009Case notesBuiltCorecase_notes
rev.010Case owner assignmentBuiltExpectedcases.owner
rev.011SLA per case with overdue highlightingBuiltExpectedcaseSla in admin.html
rev.012Queue grouped by SLA stateBuiltExpectedoverdue / due today / new
rev.013Search by name, id or e-mailBuiltExpectedGET /v2/applicants?q=
rev.014Filter by risk bandBuiltExpectedrisk=high|medium|low
rev.015Filter by reviewerBuiltExpectedreviewer=
rev.016Pagination on the queueBuiltExpectedlimit and offset, capped at 500
rev.017Keyboard shortcuts for the review loopBuiltExtraadmin.html — ⌘K and queue keys
rev.018Bulk actions on a filtered setPartialExpectedPOST /v2/applicants/bulk assigns, escalates, requests a resubmission and annotates in bulk; approve and reject are refused by design — a bulk approve is how one mistake becomes two hundred
rev.019Reviewer workload viewBuiltExtraadmin analytics
rev.020Watchlist of applicants to keep an eye onBuiltExpectedadmin watchlists view
rev.021Saved queue filtersBuiltExtrasaved_filters — per user, optionally shared with the team
rev.022Export the queue to CSVBuiltExpectedGET /v2/export/applicants.csv
rev.023An approval the engine refuses cannot be forced from the UIBuiltCorethe console shows the refusal and reverts
rev.024Resubmission request reaches the applicantPartialExpectedneeds an SMTP account
rev.025Side-by-side comparison of two applicantsBuiltExtraGET /v2/applicants/compare — says which fields agree, and the read is audited against both

Alerts 17/18

IDFeatureStatusPriorityWhere to check it · what it needs
alr.001Alerts raised by the engine with a severityBuiltCorealerts table · GET /v2/alerts
alr.002Alert linked to the applicant that caused itBuiltCorealerts.applicant_id
alr.003Open, acknowledged and closed statesBuiltCorePATCH /v2/alerts/:id
alr.004Unknown alert status refused rather than storedBuiltCorevalidated against a known set
alr.005Alert detail explains what fired and whyBuiltCorealerts.detail
alr.006Alert types catalogued with category and iconBuiltExpectedA.data.alertTypes, extended by engine codes
alr.007An engine code the UI has never seen still rendersBuiltExpectedlive.js synthesises a label rather than showing blank
alr.008Alert feed with a live clockBuiltExpectedadmin feed
alr.009Unread count badgeBuiltExpectedadmin bell
alr.010Alert routing rules per clientBuiltExpectedconsole rules and alerts view
alr.011Alert delivery by webhookBuiltExpectedalert.created event
alr.012Alert delivery by e-mailPartialCoreneeds an SMTP account
alr.013Alert delivery to SlackBuiltExtraserver/webhooks.js — Slack body shape, same queue and retries; carries ids, never names
alr.014Alert history retained for auditBuiltExpectedalerts survive the document retention clock
alr.015Alert volume trendBuiltExtraanalytics series
alr.016Acknowledging an alert is auditedBuiltExpectedaudit category alerts
alr.017Alert suppression for a known false positiveBuiltExpectedalert_suppressions — a suppressed alert is still recorded and attributed, never dropped
alr.018Severity thresholds configurableBuiltExpectedtenants.settings

Client configuration 29/32

IDFeatureStatusPriorityWhere to check it · what it needs
cfg.001Multi-tenant: every query scoped to one clientBuiltCoreguard() is the only way to obtain a tenant id
cfg.002Cross-tenant access refused even with a forged headerBuiltCoreverified — x-hawkai-tenant returns 403
cfg.003Self-serve client sign-upBuiltCorePOST /v2/auth/signup
cfg.004Sign-up refuses when storage would not survive a rebuildBuiltCore503 with blocked_by: persistence
cfg.005Platform admin can provision a clientBuiltCorePOST /v2/tenants
cfg.006Provisioned owner has no password until they set oneBuiltCorean admin never knows a client credential
cfg.007Self-serve sign-up can be closedBuiltExpectedSIGNUP_OPEN=0
cfg.008Go-live checklist derived from stored stateBuiltCoreGET /v2/tenant/onboarding — nothing tickable by hand
cfg.009Checklist distinguishes "endpoint saved" from "delivered"BuiltCorecounts webhook_deliveries, not webhooks
cfg.010Client settings merged, never replaced, on a partial saveBuiltCorePUT /v2/tenant/settings
cfg.011Settings must be an objectBuiltCorea string used to spread into {0:"n",1:"o"}
cfg.012Sandbox and production environmentsBuiltExpectedapi_keys.env · console env switch
cfg.013Flow builder: order and configure the applicant journeyBuiltExpectedconsole flows view · GET /v2/tenant/flows
cfg.014Flow versioning with a published versionBuiltExpectedflows table
cfg.015Branding: name, colour, headline, messageBuiltExpectedtenants.branding
cfg.016Branding preview on a phone frameBuiltExpectedconsole branding view
cfg.017Branded flow language setBuiltExpectedper-link locale
cfg.018Custom domain for the hosted flowNot startedExtrasingle domain today
cfg.019Plan and seat count on the client recordBuiltExpectedtenants.plan · seats
cfg.020Client list for platform staffBuiltExpectedconsole clients view
cfg.021A client sees only their own workspaceBuiltCorelive.js adoptRealTenants — was showing sample clients
cfg.022A client never sees fabricated API keys or webhooksBuiltCorelive.js adoptRealIntegrations — was showing sample ones
cfg.023Retention windows configurable per clientBuiltExpecteddocumentRetentionDays · retentionDays
cfg.024Data residency selectionNot startedExpectedone database in one region
cfg.025Client-level feature flagsBuiltExtratenants.settings is free-form and merged
cfg.026Client status: active, trial, pausedBuiltExpectedtenants.status
cfg.027Pausing a client stops new verificationsBuiltExtraPOST /v2/tenant/pause — gates link creation, API creation and the applicant’s own submission; existing cases can still be decided
cfg.028Usage counted per client per dayBuiltExpectedGET /v2/tenant/usage — counted from the applicant rows, not from a counter, because a counter drifts and a billing number that drifts cannot be defended
cfg.029Invoices per clientBuiltExpectedGET /v2/tenant/invoices — one per closed month, written once; the current month is a live quote, never an invoice
cfg.030Billing is per completed verificationBuiltExpectedserver/billing.js priceFor — a verification counts when it reached a decision, which is what the pricing page says
cfg.031Self-serve plan upgradeBuiltExpectedPOST /v2/tenant/plan — starter and growth apply at once and are invoiced; enterprise is recorded as a request rather than granted, because it is a contract
cfg.032Payment method captureNot startedExtrano payment provider connected

Identity and security 41/47

IDFeatureStatusPriorityWhere to check it · what it needs
sec.001Password sign-inBuiltCorePOST /v2/auth/login
sec.002Passwords hashed with scryptBuiltCoreserver/crypto.js hashPassword
sec.003Password strength enforced at sign-upBuiltCorelength, character classes, obvious-choice rejection
sec.004Session tokens HMAC-signedBuiltCoreserver/crypto.js sign/verify
sec.005Sessions revocable individuallyBuiltCorePOST /v2/auth/logout · sessions.revoked_at
sec.006All other sessions revocable at onceBuiltCorerevokeAllSessions
sec.007Changing a password revokes existing sessionsBuiltCoreauth.setPassword → revokeAllSessions
sec.008Session cookie is HttpOnly and SecureBuiltCoreset-cookie on login
sec.009Bearer token accepted for API clientsBuiltCoreauthorization header
sec.010Two-factor authentication (TOTP)BuiltCorePOST /v2/auth/mfa/setup and /confirm
sec.011TOTP secret stored encryptedBuiltCoreusers.totp_secret via crypto.encrypt
sec.012TOTP enrolment QR and manual keyBuiltExpectedauth.beginTotp returns an otpauth URI
sec.013Backup codes for two-factorBuiltExpectedten single-use codes issued when two-factor is enabled, stored as hashes, spent codes kept with the date
sec.014Five roles with distinct permissionsBuiltCoreowner, admin, reviewer, auditor, developer
sec.015Auditor role reads everything and changes nothingBuiltCoreCAN.auditor
sec.016Permission checked on every routeBuiltCoreguard(req,res,action)
sec.017Role names validated on invite, case-insensitivelyBuiltCorerejects an unknown role
sec.018Scoped API keysBuiltCorePOST /v2/tenant/keys
sec.019API key scopes validated against a known listBuiltCorerejects "*" and typos
sec.020API keys hashed at rest, shown onceBuiltCoreapi_keys.key_hash
sec.021API key revocationBuiltCoreDELETE /v2/tenant/keys/:id
sec.022API key last-used timestampBuiltExpectedapi_keys.last_used_at
sec.023Invitations with a single-use expiring linkBuiltCoreinvitations table · 7 days
sec.024Invitation token hashed at restBuiltCoretoken_hash only
sec.025Accepting an invitation sets a password and signs inBuiltCorePOST /v2/auth/invite/accept
sec.026Admin can re-issue an invite or a reset for a colleagueBuiltCorePOST /v2/tenant/team/:userId/invite
sec.027Self-serve password resetPartialCoreneeds an SMTP account
sec.028Reset response identical for every addressBuiltCorecannot be used to discover who has an account
sec.029Reset link lives one hour, not a weekBuiltCoreissueInvite hours:1
sec.030Personal data encrypted at rest (AES-256-GCM)BuiltCoreserver/crypto.js encryptFields
sec.031Data key separate from the session-signing keyBuiltCoreSECRET_KEY vs JWT_SECRET
sec.032Rate limiting on sign-inBuiltCore10/min per IP
sec.033Rate limiting on sign-upBuiltCore5/hour per IP
sec.034Rate limiting on password resetBuiltCore5 per 15 min
sec.035Webhook URLs rejected if they resolve inside our networkBuiltCoreloopback, link-local, private, unique-local, IPv4 and IPv6
sec.036Credentials in a webhook URL rejectedBuiltCorewebhookUrlProblem
sec.037Malformed input returns 4xx, never 5xxBuiltCoreprobed across every route
sec.038Security headers on every responseBuiltCorenosniff, referrer-policy, frame-ancestors
sec.039Edge rate limitingNot startedExpectedin-process limits stop a script, not a botnet
sec.040Single sign-on (OIDC)Not startedExpectedneeds an identity provider (an OIDC issuer, client id and secret)
sec.041Passkeys (WebAuthn)BuiltExpectedserver/webauthn.js — own CBOR/COSE parsing and ES256 verification, no dependency; register in the console, sign in on /sign-in
sec.042An unauthenticated caller cannot write into any tenantBuiltCoreclosed — verify/submit took a tenant from the body
sec.043Vulnerability disclosure route publishedBuiltExpectedcontent/security.md
sec.044Findings published with what was done about themBuiltExpectedcontent/security.md — four so far
sec.045Penetration testNot startedExtranot performed — stated plainly on the trust page
sec.046SOC 2 Type IINot startedExtrano audit begun — stated plainly
sec.047ISO 27001Not startedExtrano audit begun — stated plainly

API and webhooks 29/30

IDFeatureStatusPriorityWhere to check it · what it needs
api.001REST API under /v2BuiltCore51 routes
api.002API reference generated from the route tableBuiltCoretools/build-pages.js — cannot describe a route that does not exist
api.003Required scope documented per routeBuiltCoreread from the guard() call
api.004Conventional status codes with a readable errorBuiltCoreerror field written for a person
api.005Field-level validation errors name the fieldBuiltCore{ error, field }
api.006503 names what is missingBuiltCore{ blocked_by }
api.007429 returns retry_afterBuiltCorerateLimit
api.008Webhooks with HMAC-SHA256 signaturesBuiltCoreserver/webhooks.js
api.009Signature covers timestamp.body to stop replayBuiltCoredocumented with a verification snippet
api.010Webhook retries with backoffBuiltCore6 attempts
api.011Webhook delivery logBuiltCorewebhook_deliveries · shown in the console
api.012Webhook ping to test an endpointBuiltCorePOST /v2/tenant/webhooks/:id/ping
api.013Webhook secret shown onceBuiltCorereturned on creation only
api.014Event types for applicant lifecycle and alertsBuiltExpectedapplicant.* and alert.created
api.015Event subscription per endpointBuiltExpectedwebhooks.events
api.016Idempotent applicant creationBuiltExpectedIdempotency-Key header; the same key with a different body is a 409, not a silent replay
api.017Verification session creation via APIBuiltExpectedPOST /v2/verification-sessions
api.018Public session lookup for a hosted flowBuiltExpectedGET /v2/verify/session/:token
api.019Quickstart documentationBuiltExpectedcontent/docs.md
api.020Webhook verification example in a real languageBuiltExpectedNode snippet with timing-safe compare
api.021Web SDKBuiltExpectedpublic/assets/js/hawkai-sdk.js — one file, no dependencies; the flow runs in an iframe and posts the outcome back, origin-checked
api.022iOS and Android SDKsPartialExtrano native package; the supported mobile path is the hosted flow in a web view, documented with working Swift and Kotlin, including the camera permission both need
api.023OpenAPI specificationBuiltExpected/openapi.json — generated from the route table at build time
api.024CSV export of applicantsBuiltExpectedGET /v2/export/applicants.csv
api.025Capability endpoint: what this deployment can doBuiltExpectedGET /v2/capabilities
api.026Readiness endpoint an operator can trustBuiltCoreGET /readyz — 503 until the blocking items pass
api.027Health endpoint with storage and backup stateBuiltCoreGET /healthz
api.028Neither health endpoint requires a loginBuiltCorea status endpoint you must authenticate to is not one
api.029Screening list status via APIBuiltExpectedGET /v2/screening/lists
api.030Sandbox test identities that produce known outcomesBuiltExtraconsole integrations — test applicants

Data protection 28/30

IDFeatureStatusPriorityWhere to check it · what it needs
dp.001Document images deleted on a scheduleBuiltCoreserver/retention.js — 90 days by default
dp.002Retention window configurable per tenantBuiltCoresettings.documentRetentionDays · retention.settingsFor
dp.003Record retention separate from document retentionBuiltCoredefault 2555 days — the AML obligation
dp.004Retention sweep runs on its own, not on requestBuiltCore6-hourly timer
dp.005Deletion writes a tombstone to the audit logBuiltCorewhat was deleted, when, by which rule
dp.006Deletion is real, not a flagBuiltCorethe row content is overwritten, not hidden
dp.007Legal documents state the real retention periodBuiltCorediffed against the code constants in 14 languages
dp.008Privacy notice shown before a document is uploadedBuiltCorethe applicant reads it before it is too late to decline
dp.009Explicit consent recorded with a timestampBuiltCoreconsents table — kind, granted, ip, at
dp.010The consent wording is stored, not a version pointerBuiltCoreconsents.text — an old consent can be read exactly as it was given
dp.011Subject access exportBuiltCoreGET /v2/applicants/:id/data — record, documents, decisions, consents, alerts, access log
dp.012Erasure request handlingBuiltCorePOST /v2/applicants/:id/erase — honours the AML hold
dp.013Erasure refuses when a record is under a legal hold, and says soBuiltCorea quiet partial deletion is worse than a clear refusal
dp.014Rectification of a stored fieldBuiltExpectedPATCH /v2/applicants/:id — reason required, previous value kept in the audit entry
dp.015Data processing purpose stated per field groupBuiltCorecontent/privacy.md
dp.016Sub-processors listed by name and roleBuiltCorecontent/privacy.md — Hugging Face today
dp.017DPA published rather than sent on requestBuiltCorecontent/dpa.md
dp.018Personal data never written to application logsBuiltCorelog lines carry ids, not names or numbers
dp.019Webhook payloads carry ids, not document imagesBuiltCoreserver/webhooks.js
dp.020Export excludes other tenants by construction, not by filterBuiltExpectedevery query is tenant-scoped at the statement
dp.021Backups encrypted and access-controlledBuiltExpectedprivate Dataset repository
dp.022Backup restore tested end to endBuiltExpectedsnapshot → clear → fetch → boot
dp.023Breach notification commitment in writingBuiltCorecontent/dpa.md — 72 hours
dp.024Data residency choiceNot startedExpectedone region today; stated plainly rather than implied
dp.025Customer-managed encryption keysNot startedExtrakeys are deployment-level
dp.026Minimisation: the flow asks for nothing it does not useBuiltExpectedeach field maps to a check or an obligation
dp.027An applicant can see what was collected about themBuiltExpectedthe completion screen lists it
dp.028Automated-decision disclosureBuiltExpectedthe applicant is told a decision may be automated and can ask for review
dp.029Records of processing activityBuiltCorecontent/privacy.md + the audit log together
dp.030Deletion propagates to backups within one cycleBuiltExpectedsnapshots are full, not incremental — the next one no longer holds it

Reporting 25/26

IDFeatureStatusPriorityWhere to check it · what it needs
rep.001Live counts of applicants by statusBuiltCoreconsole overview
rep.002Approval, rejection and referral ratesBuiltCorecomputed from decisions, not entered
rep.003Pass rate over timeBuiltCoreconsole chart, own SVG
rep.004Median and 90th-percentile time to decisionBuiltCoreGET /v2/analytics/breakdown — a mean hides the queue
rep.005Volume by countryBuiltCoreGET /v2/analytics/breakdown — by_country, from the document then the address
rep.006Volume by document typeBuiltCoreGET /v2/analytics/breakdown — by_document_type
rep.007Drop-off by step of the flowBuiltCorewhere applicants abandon
rep.008Reviewer throughput per personBuiltExpecteddecisions per reviewer per day
rep.009Override rate: how often a human disagrees with the engineBuiltExpectedthe number that tells you the rules are wrong
rep.010Rule hit countsBuiltExpectedwhich rule actually fires
rep.011Rules that never fire are listedBuiltExpecteddead rules are a liability, not a control
rep.012Screening hit counts and referral rateBuiltCoremeasured — 9% on a 23-name control set
rep.013Alert volume and time to closeBuiltExpectedGET /v2/analytics/breakdown — alerts.time_to_close_minutes
rep.014Case ageing: what is sitting too longBuiltExpectedoldest-first queue with an age column
rep.015SLA breach countBuiltExpectedagainst the configured review SLA
rep.016CSV export of any table shownBuiltCorea report you cannot export is a screenshot
rep.017Date-range filter on the reports that read live rowsBuiltExpectedfrom/to on /v2/analytics/breakdown, /v2/audit and both CSV exports
rep.018Durations formatted with CLDR short unitsBuiltExpectednarrow units are Latin in Japanese — a real bug we hit
rep.019Charts drawn without a charting libraryBuiltExpectedinline SVG — nothing to load, nothing to break
rep.020Charts readable in both themesBuiltExpectedcolours from CSS variables
rep.021Empty states say "no data yet", never show a zero as a resultBuiltExpectedthe breakdown returns a note instead of zeros; the consoles render .empty panels
rep.022Regulator-facing summary of a periodBuiltExpectedcounts, rates, and the rule set in force
rep.023Audit log searchable by actor, object and dateBuiltExpectedGET /v2/audit — category, free text, from/to
rep.024Audit log exportBuiltExpectedGET /v2/export/audit.csv — same filters as the screen
rep.025Scheduled report e-mailPartialExtraneeds an SMTP account
rep.026Warehouse exportBuiltExtraGET /v2/export/warehouse.ndjson — applicants with their decisions and alerts, one JSON record per line

Languages and accessibility 32/32

IDFeatureStatusPriorityWhere to check it · what it needs
i18n.001Fourteen languages across the whole productBuiltCoreen, ja, ko, zh, fr, it, es, th, ms, id, hi, ro, ru, ar
i18n.002The marketing site, the console and the applicant flow all translateBuiltCoreone catalogue, not three
i18n.003Translation keyed by the English source stringBuiltCorea new sentence cannot silently lose its translation key
i18n.004Dynamically inserted text translates tooBuiltCoreMutationObserver
i18n.005Original English kept so a language can be switched backBuiltCoreWeakMap of originals — no reload
i18n.006Numbers inside a translated sentence normalisedBuiltCore{n} placeholder — one entry covers every count
i18n.007Names substituted after translation, never mid-sentenceBuiltCoresplitting a sentence breaks Japanese and Korean word order
i18n.008Legal bodies pinned so a machine pass cannot touch themBuiltCoredata-no-i18n
i18n.009Language chosen from a picker and rememberedBuiltCorelocalStorage + the URL prefix
i18n.010Language-prefixed URLs that can be linked and indexedBuiltCore/<lang>/<page> · 154 URLs in the sitemap
i18n.011hreflang across every page and languageBuiltCoregenerated, not hand-written
i18n.012Right-to-left layout for ArabicBuiltCoredir=rtl, mirrored spacing, logical CSS properties
i18n.013Arabic shown with Latin digitsBuiltCorear-u-nu-latn — the finance convention in the Gulf
i18n.014Dates, times and currencies in the reader localeBuiltCoreIntl
i18n.015CJK line breaking not broken by our own wrappingBuiltCoreno manual breaks inside sentences
i18n.016The document language attribute set before first paintBuiltCorein the head, so screen readers start right
i18n.017Language coverage measured in a real browser, not counted in a fileBuiltCoretools/test/verify-langs.py — 13 languages × 6 surfaces
i18n.018The coverage check fails the build when a string regressesBuiltCoreand it caught its own inverted metric
i18n.019Applicant instructions translated, including the error textBuiltExpectedthe messages that matter most are the failures
i18n.020E-mail subjects and bodies translatedBuiltExpectedRFC 2047 encoded subjects
i18n.021Country names translatedBuiltExpectedA.country() — Intl.DisplayNames, falling back to the English name
i18n.022Document type names translatedBuiltExpectedPassport, National ID, Residence permit and the rest are catalogue keys
i18n.023Decision reasons translatedBuiltExpectedso an applicant reads why in their own language
i18n.024Translation catalogue exportable for human reviewBuiltExtra3,100 keys as JSON
i18n.025Keyboard reachable throughoutBuiltCoreno control that only a mouse can reach
i18n.026Visible focus ring everywhereBuiltCorenever removed without a replacement
i18n.027Form fields have real labels, not placeholders as labelsBuiltCoreevery field in verify.html carries a label with a for attribute
i18n.028Errors announced to assistive technologyBuiltCorearia-live on the validation region
i18n.029Colour is never the only signalBuiltCorestatus carries a word as well as a colour
i18n.030Contrast audited in both themesBuiltCoreCDP sweep over computed colours
i18n.031Reduced-motion respectedBuiltExpectedprefers-reduced-motion
i18n.032Camera step usable one-handed on a phoneBuiltExpectedcontrols within thumb reach

Site and trust 22/22

IDFeatureStatusPriorityWhere to check it · what it needs
web.001Marketing site, console and applicant flow on one deploymentBuiltCoreone origin, one certificate, one language switch
web.002Light and dark themesBuiltCoreCSS variables — both audited for contrast
web.003Theme follows the system and can be overriddenBuiltCoreremembered per browser
web.004One logo rendered from one source everywhereBuiltCoreA.logo / A.lockup
web.005Favicon, app icon and social image from the same markBuiltCorefavicon.svg, mark.webp, apple-touch-icon.png, og.jpg
web.006Palette derived from the mark, not chosen next to itBuiltCoredocs/DESIGN.md — the tokens and where they came from
web.007Pages generated from Markdown, not hand-edited HTMLBuiltCoretools/build-pages.js
web.008Sitemap and robots.txt generatedBuiltCore154 URLs
web.009Meta description and title per page and languageBuiltCoretools/build-pages.js — canonical plus hreflang alternates
web.010Open Graph and Twitter cardsBuiltCoretools/build-pages.js and public/index.html
web.011Structured data for the organisation and the productBuiltExpectedJSON-LD graph, generated from the same strings as the page
web.012No third-party script on any pageBuiltCoreno analytics, no fonts, no tag manager — nothing to leak an applicant
web.013No cookie banner because there is nothing to consent toBuiltCoreonly the session cookie, which is strictly necessary
web.014Pricing publishedBuiltCorethe pricing section on the landing page — per-verification, with what each tier includes
web.015What is not built is publishedBuiltCorecontent/status.md — the honest list
web.016Public changelog, updated in the same commit as the changeBuiltCoredocs/CHANGELOG.md
web.017Security page with the disclosure route and past findingsBuiltCorecontent/security.md
web.018Trust page stating which audits exist and which do notBuiltCorenone yet — said plainly
web.019Terms, privacy notice, DPA and cookie notice publishedBuiltCorecontent/*.md — the chrome translates; the bodies stay English and say so, because a machine-translated contract is not the contract
web.020Documentation with a working quickstartBuiltExpectedcontent/docs.md
web.021Feature catalogue published with its real statusBuiltExpectedserver/features.js → /features and GET /v2/features
web.022Every page works with JavaScript disabled for readingBuiltExpectedcontent is in the HTML

Operations 35/35

IDFeatureStatusPriorityWhere to check it · what it needs
ops.001Runs with no third-party runtime dependencyBuiltCorepackage.json has no dependencies — nothing to audit, nothing to patch
ops.002Single container, single portBuiltCoreDockerfile · 7860
ops.003Boots with no configuration at allBuiltCoresafe defaults; everything optional is announced as unset
ops.004Secrets read from the environment onlyBuiltCoreno secret is committed, and none is printed
ops.005Generated keys warn loudly that they are ephemeralBuiltCorea restart would invalidate sessions — the operator is told
ops.006SQLite with durable settingsBuiltCorejournal_mode DELETE, synchronous FULL, busy_timeout
ops.007Live database never on network storageBuiltCorea FUSE mount corrupts SQLite — learned the hard way
ops.008Snapshots taken with VACUUM INTO, not a file copyBuiltCorea copy of an open database is not a backup
ops.009Durable storage without a paid diskBuiltCoreprivate Dataset repository as the backing store
ops.010Snapshot pushed on a schedule and on shutdownBuiltCoreserver/cloud-push.js
ops.011Snapshot fetched and adopted at boot when the disk is emptyBuiltCoreserver/cloud-fetch.js — a rebuild does not lose accounts
ops.012A newer local database is never overwritten by an older snapshotBuiltCorecompared before adopting
ops.013Local development cannot write to production storageBuiltCoreguarded on SPACE_ID — after a local test polluted it once
ops.014Backup state visible on the health endpointBuiltCorelast push, last fetch, and why it is blocked if it is
ops.015A directory given as the database path is handledBuiltCoreapp.db is created inside it rather than failing forever
ops.016Schema applied idempotently at bootBuiltCoreserver/schema.sql plus ADD_COLUMNS in server/db.js — a new column reaches an existing database
ops.017Migrations never drop a column or a tableBuiltCoreADD COLUMN only — a deployment must not be able to destroy client data
ops.018Uploads and configuration survive a redeployBuiltCorerestored from the snapshot, never re-initialised
ops.019Graceful shutdown: finish in-flight work, then snapshotBuiltCoreSIGTERM handler
ops.020Structured request logging without personal dataBuiltCoreserver.js request log — method, path, status, duration
ops.021Unhandled errors logged with a correlation id and a 500 that says nothing elseBuiltCorethe response carries `reference`, the stack stays in the log
ops.022Health endpoint reports storage, backup and screening stateBuiltCoreGET /healthz
ops.023Readiness endpoint refuses traffic until the blocking items passBuiltCoreGET /readyz — document, liveness, admin today
ops.024Readiness distinguishes "not configured" from "passing"BuiltCorethe distinction the whole compliance posture rests on
ops.025HTML served no-cache, assets cached for an hourBuiltCorea stale HTML makes a fixed bug look unfixed
ops.026Static assets fingerprintedBuiltExpectedserver.js fingerprint() — references get ?v=<content hash> as the page is served, and a versioned request is answered immutable for a year
ops.027Gzip on text responsesBuiltCorezlib
ops.028Screening lists refreshable without a deployBuiltExpectedPOST /v2/screening/refresh · tools/load-sanctions.js
ops.029List load is transactional — a failed refresh keeps the old listBuiltExpectednever leaves screening with a half list
ops.030List provenance and load date shownBuiltExpectedso a reviewer knows how stale a hit is
ops.031API surface regression-testedBuiltCoretools/test — every route probed for 4xx-not-5xx
ops.032Inline scripts syntax-checkedBuiltCoretools/test/inline-syntax-check.py — node --check cannot see them
ops.033Screening precision measured, with a failing thresholdBuiltCoretools/test/screening-precision.js — 6/6 recall, 9% referral
ops.034Real-browser verification over every page and languageBuiltCoreCDP sweep, 78 rows, 0 JS errors
ops.035Test suites clean up after themselvesBuiltExpectedso two runs in a row give the same answer

Go-live 17/20

IDFeatureStatusPriorityWhere to check it · what it needs
live.001Self-serve sign-up that creates a real tenantBuiltCorePOST /v2/auth/signup
live.002First account becomes the ownerBuiltCoreno seeded admin password to forget to change
live.003Guided onboarding with a completion state per stepBuiltCoreGET/POST /v2/tenant/onboarding
live.004Onboarding cannot be marked complete while a blocker standsBuiltCorereads the same readiness as /readyz
live.005Go-live checklist in the console showing what is missingBuiltCorerenderGoLive
live.006The checklist names the owner of each blockerBuiltCoreours or yours — no ambiguity about who is waiting
live.007Colleagues invited by e-mail with a roleBuiltCorePOST /v2/tenant/team — role validated against the five that exist
live.008An invitation works without mail configuredBuiltCorethe link is shown to the admin to pass on — otherwise onboarding deadlocks
live.009Branding: name, logo and colour per tenantBuiltCoreapplied to the hosted flow and the e-mails
live.010Verification links created from the consoleBuiltCoresingle-use, expiring, one per applicant
live.011Hosted flow shows the client name, in every languageBuiltCore{client} and {email} resolved after translation, on the result screen too
live.012Test mode with identities that produce known outcomesBuiltCorea customer can rehearse a rejection
live.013Test data clearly marked and separately deletableBuiltCorenever mixed into the real counts
live.014Demo tenant removable without touching real tenantsBuiltCoreserver/bootstrap.js seeds it as its own tenant id
live.015Operator runbookBuiltCoredocs/GO-LIVE.md — what to set, in what order, and what it unblocks
live.016Every required secret listed with what breaks without itBuiltCoredocs/GO-LIVE.md
live.017Nothing is faked to look configuredBuiltCorethe rule the whole catalogue follows
live.018Document-authenticity providerNot startedCoreneeds a document-authenticity provider
live.019Face-match and liveness providerNot startedCoreneeds a face-match and liveness provider
live.020PEP and adverse-media dataNot startedCoreneeds a commercial PEP / adverse-media data set