Add V-16 retail spending validation#274
Conversation
|
@Emelie-Dev Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
…mo-login JWT issuance (ericmt-98#277)
…-98#253) Wave 6 batch 2 (V-16…V-25). First-person, privacy-first answer on NFC contactless tap-to-pay familiarity and trust vs PIN / QR / cash, for the retail vertical (Claim 4 + 6). No names, amounts, or financial details. Co-authored-by: PC <pc@PCs-MacBook-Pro.local> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
First-person response for issue ericmt-98#237 (V-22). Validates Claim 4 — passkey/biometric recovery architecture earns trust over seed phrases. - Adds ### V-22 section to VALIDATION_DRIPS.md - Registers V-22 row in WAVE6_RESEARCH_ISSUES.md Closes ericmt-98#237
Creates docs/validation-reports/ with one structured .md per contributor response — V-16 (consumer spending, Mexico), V-17 (abarrotes merchant, Mexico), V-18 (NFC vs QR, Nigeria), V-20 (split payroll, Mexico), V-22 (key recovery, Latin America). Each file includes the full first-person response, SDF narrative, and a key-findings table for product use. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Added comprehensive security audit report for issue ericmt-98#257 - Documented clipboard exposure risks on Android (inter-app access, keyboard logging, device sync) - Provided reproduction steps tested on Android 12-13 - Suggested fix options: automatic cleanup, QR code, encrypted backup, etc. - Severity: High (control of wallet funds) - Per audit scope: report only, no code changes implemented Co-authored-by: Stellar Intel Dev <dev@stellar-intel.dev>
* Security audit: SEC-26 double identity persistence in micopay_users Closes ericmt-98#258 * Security audit: SEC-28 WebView without CSP and remote resource loading Closes ericmt-98#260
Co-authored-by: peace0git <peace0git@gmail.com>
GET /api/v1/cash/request/:id was registered with no preHandler — no auth
and no x402 verification — so any unauthenticated caller who knew or
guessed a request_id received 200 OK leaking merchant_name, amount_mxn,
amount_usdc, htlc_tx_hash and expires_at. IDs are mcr-{8 hex}, an
enumerable ~4.3e9 space, and the 200 vs 404 distinction made the endpoint
an existence oracle throttled only by the global 100 req/min limit.
Gate the endpoint to match the existing GET /api/v1/swaps/:id/status
pattern: x402 micropayment (0.0001 USDC, service cash_request_status)
plus a strict 20 req/min per-route rate limit as defense in depth.
Add a regression test and the SEC-03 security report.
Previously, if fetchReputationRoot() threw (e.g. Soroban RPC unreachable), the catch block silently swallowed the error and forwarded the proof to the contract, opening a window where an attacker could submit a fabricated Merkle root during an outage. The Soroban contract has no duplicate root guard. - Remove the try/catch from fetchReputationRoot() so network errors propagate - Change the route handler catch to return 503 instead of a non-fatal warning - Add three new tests covering the SEC-08 fatal guard for reputation_v1, access_credential_v1, and verifying poseidon_preimage is unaffected - Fix the mock structure (vi.hoisted shared fns) so per-test overrides work - Update circuit count assertion to include access_credential_v1 (3 total) - Add security report at docs/security-reports/SEC-08-zk-merkle-root-no-fatal.md Fixes ericmt-98#215
- Add verifyWebhookSignature() with HMAC-SHA256 and timingSafeEqual - Integrate verification into POST /defi/ramp/webhook - Add WEBHOOK_SECRET to config.ts and .env.example - Include replay protection via x-webhook-timestamp (±5 min) - Create security report at docs/security-reports/SEC-20-ramp-webhook-sin-verificar.md Co-authored-by: michael philip <philipmichaelonyekachi>
- getAuthToken() now sends stellar_address (from getPublicKey()) instead of username in both /auth/challenge and /auth/token requests, matching the backend schema (additionalProperties: false, stellar_address required) - Add online?: boolean to Offer interface in ExploreMap.tsx — the field was already referenced in OfferConfirmData but missing from the type, causing tsc build failures - Add docs/security-reports/SEC-11-auth-mismatch-cliente-servidor.md Closes ericmt-98#218
Replace direct window.localStorage reads of auth_token, micopay_users, and token with readJSON from secureStorage.ts so that on native builds (Capacitor) the Keychain/Keystore path is used, closing the bypass identified in the SEC-22 audit. - TradeDetail.tsx: isCurrentUserBuyer → async + readJSON; isBuyer lifted to useState/useEffect - useChatMessages.ts: getAuthToken() helper wraps readJSON; all three fetch calls await it - reportError.ts: readJSON inside fire-and-forget .then().catch() chain - docs/security-reports/SEC-22-localstorage-secure-storage.md: audit report Closes ericmt-98#254
Reject malformed secret and htlc query params, gate legacy MICOPAY scheme to demo builds, and add security report for issue ericmt-98#262. Co-authored-by: Cursor <cursoragent@cursor.com>
Adds completionRate, tradesCompleted, tier, isBusiness fields to Offer interface and displays them on ExploreMap and DepositMap cards. Co-Authored-By: SaviourBosan <saviourmichael444@gmail.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds effectiveFeePercent() helper and MAX_EFFECTIVE_FEE_PERCENT=5 constant to api.ts; ExploreMap and DepositMap now display the combined commission + platform fee and warn when it exceeds the 5% threshold identified by market validation (V-1/V-3/V-7/V-8). Co-Authored-By: adepoju2006 <adepoju2006@github.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds useWalletBalance hook that queries Horizon directly for the user's USDC/XLM balances, replacing the previous hardcoded/mock values in the Home screen. Co-Authored-By: Olamidepy <olamidepy@github.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds KYCScreen.tsx with pending/approved/rejected states, deep-link callback via Capacitor App, and status persistence via secureStorage. Wires KYC into App.tsx routing and CETESScreen navigation. KYC types (startKYC, getKYCStatus) added to api.ts. Co-Authored-By: dhareymu <dhareymu@github.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…polling Adds 'spei' tab to CETESScreen with 3-step flow: quote request, CLABE instructions with QR code, and status polling. Integrates KYC gate, bank account registration, and ramp order management via new API functions (getRampQuote, createRampOrder, getRampOrderStatus, registerBankAccount). Co-Authored-By: Abdulrasaq1515 <abdulrasaq1515@github.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Gracias por la validación V-16 🙏 El contenido está muy bien. Solo un detalle de mecánica: el PR quedó en conflicto con |
… state machine (ericmt-98#227) - Add micopay/backend/src/tests/tradeAuth.test.ts with 9 regression tests covering lockTrade (seller-only), revealTrade (seller-only), getTradeSecret (seller-only), completeTrade (buyer-only), and getTradeById (participants-only) guards - Add test:trade-auth npm script to micopay/backend/package.json - Add docs/security-reports/SEC-10-state-machine-regresion.md report All 9 tests pass. tsc build is clean. Closes ericmt-98#217 Co-authored-by: ericmt-98 <eric.020.1999@gmail.com>
…ntegrated economy (ericmt-98#241) Designs and indexes 10 new market/user validation issues that extend the cash-out validation (V-1…V-15) into the next two verticals from the vision — retail spending (B) and payroll / dollar inflows (C) — plus open product questions (passkey recovery, canonical peso, supply bootstrap). Adds two new SDF claims (6: dollars get spent, 7: dollars flow in). - New: WAVE6_RESEARCH_ISSUES_BATCH2.md — gap analysis, model, index (ericmt-98#231–ericmt-98#240), full issue bodies - VALIDATION_DRIPS.md — V-16…V-25 placeholder headers for contributor PRs Issues published to milestone ericmt-98#18 (Wave 6: Market & User Validation). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Closes ericmt-98#213 Co-authored-by: ericmt-98 <eric.020.1999@gmail.com>
…x security vulnerabilities in client-errors telemetry (ericmt-98#275) Co-authored-by: ericmt-98 <eric.020.1999@gmail.com>
…rce (ericmt-98#297) The SEC-27 fix merged in ericmt-98#275 defined redactSensitiveData/redactString but never called them, and read the auth token from a non-existent flat `token` key — so client error reports still leaked unredacted stack/context and were sent unauthenticated. - Apply redactString to message/stack and redactSensitiveData to context before posting to /client-errors. - Read the token from `micopay_users` (buyer/seller.token), the key the app actually writes on login, matching the SEC-27 report's recommendation. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Route was registered in both merchants.ts and trades.ts, crashing Fastify on startup with FST_ERR_DUPLICATED_ROUTE. Kept the version in trades.ts (has schema validation + service layer). Also updates .env.testnet to point to the correct Render service URL. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ation) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Frontend: - Fix systemic safe-area overlap: every fixed-header screen now offsets content by calc(header + env(safe-area-inset-top)) so text is no longer cut off under the notch (Profile, History, CETES, Explore, ExploreMap, Blend, Cashout, MerchantInbox, QRReveal, Terms, Privacy, ChatRoom). - Profile: deterministic gradient avatar + reputation tier badge + stats (operaciones, % completadas, miembro desde). - Map: testnet builds search from a fixed CDMX origin so seeded demo merchants always appear regardless of the device GPS. Backend: - GET /users/me now returns trades_completed, completion_rate and reputation_tier computed from the trades table. - getAvailableMerchants returns trades_completed/completion_rate/tier. - Seed demo merchants with CDMX coordinates + reputation on the in-memory store so the discovery map has pins on testnet (idempotent). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A plugin-level addHook(preHandler, authMiddleware) was applying auth to the whole merchants plugin, including the public discovery endpoint — so the map's unauthenticated /merchants/available call always 401'd and the discovery map never loaded. Switch to per-route auth on the /me routes and leave /merchants/available open. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… to in-memory) The runtime pool used connectionTimeoutMillis=2000, too short for the managed Postgres first handshake on cold boot — so every start failed the initial connect and silently dropped to the ephemeral in-memory store (no JOINs/haversine/subqueries → empty map, zeroed reputation, no persistence). migrate.ts already used a 10s timeout and worked, proving the DB is reachable. - Bump connect timeout to 15s, retry the initial connect 5x with backoff. - Add a pool error handler so idle disconnects don't crash the process. - Gate the demo-merchant seed on SEED_DEMO_DATA (explicit opt-in) instead of the in-memory flag, and run it against the real DB. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…provisions Render service has no preDeployCommand guaranteed, and the previous DB was deleted. Make migrate.ts export runMigrations() and call it on startup when a real PostgreSQL connection is present, so attaching a new database creates the full schema automatically on the next deploy — no manual migrate step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… user - StatusBar.setOverlaysWebView(false): on Android env(safe-area-inset-top) is 0, so the overlaying bar sat on top of fixed headers (title colliding with the clock). Reserve the bar so headers never overlap it. - Offer cards multiplied completion_rate (already 0-100) by 100 → 8900%. Show it directly; relabel trades → ops (ExploreMap + DepositMap). - Map now uses the device's real GPS (dropped the fixed-CDMX testnet override) and the demo-merchant seed origin is configurable via SEED_ORIGIN_LAT/LNG (default northern CDMX metro), repositioning existing demo merchants on redeploy so agents appear in the user's actual zone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…c estimate /rate/xlm-mxn was throwing 503 (CoinGecko blocks shared cloud IPs), which made the wallet fall back to a fabricated x20 rate → $200,000 for 10k testnet XLM. - Send Accept + User-Agent headers (CoinGecko often blocks UA-less requests). - On upstream failure with no cache, serve a conservative configurable estimate (XLM_MXN_FALLBACK, default 2.5) marked source:fallback/stale instead of 503 — graceful degradation, no fabricated balance. - Frontend XLM->MXN fallback corrected from 20 to 2.5 (XLM is ~2-3 MXN). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rflow - Rate: CoinGecko is blocked from Render's egress IP. Compose a real rate from Binance XLMUSDT x er-api USD/MXN (both reachable from cloud) ~3.2, with CoinGecko as secondary and a marked estimate only as last resort. - ExploreMap + DepositMap offer cards: badge rows overflowed right (no flex-wrap, flex children without min-w-0). Add flex-wrap + min-w-0 + truncate on names + flex-shrink-0/whitespace-nowrap on the price column. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ources Binance is geo-blocked from Render's US egress (451) and CoinGecko 429s, so the rate stuck on the fallback estimate. Add a source chain that tries Coinbase XLM-USD then Kraken XLMUSD (both allow US/datacenter IPs) x er-api USD/MXN, with CoinGecko and Binance as later fallbacks. First valid wins. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nce fix - Pagar tab now opens a Send/Receive hub (/pay); cashout removed from the tab (still on Home). Send supports MXNe/USDC/CETES/XLM with QR scan, MAX, memo, review step and a real on-chain payment signed with the device key. Receive shows address QR + copy. New assets registry + payment service. - Startup validates the stored session against /users/me and auto re-auths an orphaned token via the device key. Fixes blank Profile. - Home: XLM row shows its own MXN value (no more double symbol); card shows total. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bootstrap i18next in main.tsx, language persisted to localStorage. Locale files es.json and en.json cover nav, home, pay, send, receive, profile. Language switcher added to Profile page as ES/EN chips. BottomNav, Home, PayHub, SendPayment, ReceivePayment, Profile use useTranslation(). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…loop Backend: POST /users/register now updates stellar_address when username exists (device keypair changed), instead of throwing 409. This unblocks users whose keypair was overwritten by the old Register bug. Frontend: getAuthToken auto-registers on 404; Register no longer overwrites existing keypair; after registration, calls onLoginSuccess directly (no separate login step required). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Login: add "Restaurar con llave secreta" — user imports their Stellar secret key to restore the device keypair and authenticate normally - Register: no 409 fallback, clear error messages - getAuthToken: remove auto-register on 404 (caused phantom accounts) - Backend: revert upsert (was insecure — anyone could claim any username) The correct recovery path is the same as any real wallet: back up your secret key at registration, import it to restore access on a new device. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- "Depositar efectivo" → "Comprar con efectivo" (ES/EN i18n) - DepositRequest: remove hardcoded fake balance, clearer description - DepositMap: "Entregas en efectivo → Recibes en wallet MXNe", "Bloqueando fondos" → "Conectando con el agente" - DepositChat: banner ahora explica que el AGENTE bloqueó los activos - DepositQR: eliminar PIN falso (no validaba nada), reemplazar con botón "Ya entregué el efectivo al agente", "Esperando encuentro" → "Ve al agente y entrégale el efectivo" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…/A-2/A-3) Backend KYC/quote/order/webhook routes called the real Etherfuse sandbox instead of in-memory stubs. Several assumptions in SPEI_ANCHOR_PLAN.md didn't match the real API and are corrected: no standalone bank-account endpoint (CLABE is captured inside the hosted KYC flow), quote/order request shapes, and the webhook signing scheme (real HMAC-SHA256 over RFC 8785 JCS-canonicalized body, one secret per event-type subscription, not the previously invented static-secret scheme). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
cetes/blend/kyc/ramp routes are gated behind config.enableInvestments (index.ts) which was never set in render.yaml — the routes pushed in ceb2f3b were 404ing in production because of this, not the deploy. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…com/Emelie-Dev/micopay-protocol into feat/v16-retail-spending-validation
|
Thanks for this — V-16 content was already integrated into |
closes #231