XpressHawala
翻译准备中
正在加载完整 README。 以下为已保存的摘录。
A working web build of the XpressTend money-transfer app from the product mockups: a
voice-first remittance experience for a Seattle, WA based money transmitter serving
customers worldwide. English is the primary language, with full translations into Somali
(Af-Soomaali), Brazilian Portuguese, Spanish and Arabic that can be switched at any time —
the whole app, not just the marketing copy. Arabic renders right-to-left.查看完整 README ↗A working web build of the XpressTend money-transfer app from the product mockups: a voice-first remittance experience for a Seattle, WA based money transmitter serving customers worldwide. English is the primary language, with full translations into Brazilian Portuguese, Spanish and Arabic that can be switched at any time — the whole app, not just the marketing copy. Arabic renders right-to-left.
npm install
npm run dev # http://localhost:5173
npm run build # type-check + production bundle into dist/
npm run preview # serve the production build
npm run lint # oxlint
The build output in dist/ is a static site — it can be dropped on any static host
(HostGator or any cPanel account, GitHub Pages, S3, Netlify, Cloudflare Pages). Routing
uses HashRouter and asset paths are relative, so there are no server rewrite rules to
configure and the site works just as well from a subfolder as from a domain root.
The site and the API are one Cloudflare Worker. A Worker route intercepts every
request to xpresstend.com ahead of any origin, which is what allows the
security headers a static host cannot set: CSP, X-Frame-Options,
X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP and HSTS.
npm run deploy # builds, deploys the isolated market frame, then the application
The shared API deploy script publishes the static-only market Worker before the application Worker. The quote frame has no customer APIs, database or secrets; see Dollar Index reference ticker. CI uses this same deployment command, so manual and automated releases publish both services.
GitHub Pages and the HostGator FTPS target are retired. Nothing is copied into
the repository root any more; the Worker serves dist/ directly.
CI runs lint, the Worker type-check, the money tests and the build on every
push and pull request. It deploys only from main, and only once a
CLOUDFLARE_API_TOKEN secret exists, so a fork builds without trying to
publish.
The site is now a marketing shopfront with a product behind a login, plus a separate staff console — the shape WorldRemit and Remitly use.
| Route | What it is | Who gets in |
|---|---|---|
/ | Public intro with a live rate calculator and account-creation call to action | Everyone |
/register, /login | Create an account first; sign-in is for returning customers | Everyone |
/app and its screens | The send-money product | Signed-in customers |
/admin | Operations console | Staff, via a separate login |
/institutional-reviewer | Read-only consumer, transfer, sub-ledger, reconciliation and audit review | Invited institutional reviewers |
Customer screens never fall back to sample recipients, balances or transfer history. A new account starts with its own empty account data.
api/ is a Cloudflare Worker on D1. Run it with npm --prefix api run dev,
deploy with npm --prefix api run deploy, and test the money rules with
npm --prefix api test.
Secrets are never in the repository. Set them once per environment:
cd api
npx wrangler secret put SESSION_PEPPER # any long random string
npx wrangler secret put STRIPE_SECRET_KEY # test key for now
SESSION_PEPPER is mixed into every password hash and is not stored in the
database, so a leaked table cannot be cracked offline. Changing it invalidates
every existing password, so set it before the first account is created.
Roles are viewer, agent, compliance, owner and reviewer. Releasing a
payout is restricted to compliance and owner, and is always recorded against
a named person in the audit log. Institutional reviewers use a distinct
sign-in route and can read consumer records, transfers, ledger postings,
reconciliation results and the audit trail; reviewer reads are themselves
recorded. They cannot manage staff, change KYC, approve transfers or write
ledger entries. Reviewer access is platform-wide: the current data model does
not scope reviewers to a separate institution or tenant.
Owners provision staff and reviewers through Invite staff or reviewer in the staff console. The invitation is single-use and expires after 48 hours; invitees choose their own password (minimum 16 characters). Do not set or share a password on another person's behalf.
Amounts are integer minor units and BigInt arithmetic — no float ever touches
one. Balances are not stored; they are derived from ledger_entries, where
every posting must net to zero within each currency. /admin/ledger/trial-balance
re-proves this on demand and the console shows a red banner if it ever fails.
Fees round up and recipient amounts round down, so rounding never costs the business money or promises the recipient more than the margin funds.
Quotes are re-priced server-side when a transfer is created, so a tampered client payload cannot buy a better rate than the corridor allows.
Payments run in test mode. Capturing a payment moves a transfer to
compliance_hold and writes the ledger, but charges nothing and releases
nothing. Going live needs, in this order:
sanctions_screenings; see
sanctions operations for refresh, freshness and review controls.api/src/routes-transfers.tsUntil then the marketing footer says so plainly, and it should stay that way.
以上为 README 的开头部分。其余内容请阅读原文。 查看完整 README ↗