Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
189 commits
Select commit Hold shift + click to select a range
248ac3e
add Alfredpay (USD/MXN/COP) on/off-ramp support to SDK
Sharqiewicz May 28, 2026
e5a7af0
fix example
Sharqiewicz Jun 3, 2026
5c43865
test(sdk): add Alfredpay handler regression tests; dedupe offramp-upd…
Sharqiewicz Jun 3, 2026
c3f5d6a
feat(frontend): tag and group Sentry API errors by domain and endpoint
Sharqiewicz Jun 17, 2026
00a0dfa
feat(frontend): filter Sentry noise and scrub PII in beforeSend
Sharqiewicz Jun 17, 2026
63bc6f3
feat(frontend): report ramp money-flow failures and add widget error …
Sharqiewicz Jun 17, 2026
75ddce9
improve Sentry Tags
Sharqiewicz Jun 17, 2026
7291e6d
add sentry-vortex skill
Sharqiewicz Jun 17, 2026
2d61816
merge with staging; address PR comments
Sharqiewicz Jun 18, 2026
4539dbe
Merge branch 'staging' into 1161-sdk-changes-for-alfredpay-currencies…
Sharqiewicz Jun 18, 2026
6b5fa3c
fix types ordering divergence
Sharqiewicz Jun 18, 2026
54f558d
chore(api): remove unused EVM_ADDRESS_REGEX from mykobo-eur-onramp test
Sharqiewicz Jun 18, 2026
0ce09a4
fix(sdk): type AlfredpayHandler signTransactions as PresignedTx[]
Sharqiewicz Jun 18, 2026
16aa529
fix(api): prevent same-chain offramp/onramp over-subsidy in finalSett…
Sharqiewicz Jun 22, 2026
a647227
feat(sdk): complete Alfredpay offramp — user-signature submission + E…
Sharqiewicz Jun 22, 2026
e7296aa
remove console.logs
Sharqiewicz Jun 22, 2026
4450c42
add exampleAlfredpayMexico to sdk
Sharqiewicz Jun 22, 2026
6c56c30
update the sdk integration docs
Sharqiewicz Jun 22, 2026
288680e
Classify unsupported SDK user transactions
ebma Jun 22, 2026
b95d3de
Align SDK quote discriminants with payment enums
ebma Jun 22, 2026
b3f9ff6
Type-check SDK ramp examples
ebma Jun 22, 2026
5ce48b7
Document SDK user transaction helpers
ebma Jun 22, 2026
dd5443a
Document Alfredpay ARS support
ebma Jun 22, 2026
5ae4580
Update final settlement subsidy spec
ebma Jun 22, 2026
a04cfd1
Align Alfredpay route security specs
ebma Jun 22, 2026
86ab505
Refresh deprecated chain lifecycle specs
ebma Jun 22, 2026
0b93dd8
Address PR review feedback
ebma Jun 23, 2026
4540c75
Refactor user transaction handling in SDK to streamline signing and b…
ebma Jun 23, 2026
fbc885d
Address code review findings
ebma Jun 23, 2026
f94a539
Small refactor of startRamp call
ebma Jun 23, 2026
b581ef2
Improve error handling for AlfredPay endpoints
ebma Jun 23, 2026
cda52ea
Address PR review feedback
ebma Jun 24, 2026
4c991f7
add userId to apikey model
gianfra-t Jun 25, 2026
daacf18
use api-key to derive user and partern id
gianfra-t Jun 25, 2026
4ed742f
add apiKey auth tests
gianfra-t Jun 25, 2026
c5d74ec
modify sdk for auth based tadId derivation
gianfra-t Jun 25, 2026
c0d42e1
use derived userId on register, alfredpay endpoints
gianfra-t Jun 25, 2026
9c1e56e
modify mykobo register unit tests
gianfra-t Jun 25, 2026
fd042de
add api-key endpoints for users
gianfra-t Jun 25, 2026
f9eabc5
adjust alfredpay quote engine for customer-derived id
gianfra-t Jun 26, 2026
d6ee74a
add script to sdk for api-key creation
gianfra-t Jun 26, 2026
52fe471
edit SKILL, gitignore
gianfra-t Jun 26, 2026
b8ff232
add EUR feature to SDK
gianfra-t Jun 26, 2026
50ff6c6
refactor api-key scripts
gianfra-t Jun 26, 2026
196747a
delete both pk and sk together
gianfra-t Jun 26, 2026
bfa7e1c
add endpoint to list fiat accounts ids on SDK, test offramp
gianfra-t Jun 29, 2026
4483f66
Merge branch 'staging' into 1161-sdk-changes-for-alfredpay-currencies…
gianfra-t Jun 29, 2026
1638271
fix(api): require user context for Alfredpay flows
ebma Jun 29, 2026
7f71247
docs(security): align API key auth specs
ebma Jun 29, 2026
618184d
refactor(api): dedupe effective-user resolution in ownership checks
ebma Jun 29, 2026
0a98385
fix(api): stop leaking Alfredpay customerId into quote notes
ebma Jun 29, 2026
1523d83
refactor(api): rename revoke pair param to pairedKeyId
ebma Jun 29, 2026
20f20db
test(api): lock in registerRamp user-gating guards
ebma Jun 29, 2026
d799b04
docs(security): record user-gated registration decision
ebma Jun 29, 2026
c936810
fix(api): derive Mykobo (EUR) identity from the effective user and ga…
ebma Jun 29, 2026
ebedf22
docs(security): document EUR identity-derivation parity for Mykobo
ebma Jun 29, 2026
2359c2f
docs(security): fix merge-mangled quote-lifecycle invariants
ebma Jun 29, 2026
46e0b63
include sk_key in mexico ramps
Sharqiewicz Jul 1, 2026
9d4f70f
fix merge conflicts
Sharqiewicz Jul 1, 2026
f850bfc
fix(sdk,api): address PR review comments (drop vestigial Stellar; rem…
Sharqiewicz Jul 1, 2026
6703997
fix refresh auth token
Sharqiewicz Jul 2, 2026
38884ab
Implement resetFailedNablaSwapOnResume function and related tests for…
ebma Jul 2, 2026
723d234
Add support for configurable profitable USDC to BRLA amount and imple…
ebma Jul 2, 2026
a87903b
Merge pull request #1241 from pendulum-chain/rebalance-more-if-profit…
ebma Jul 2, 2026
7fd8501
fix(api,sdk): restore anonymous Alfredpay quote creation via sentinel…
ebma Jul 2, 2026
a2614c1
fix(api): let authenticated callers claim anonymous quotes at ramp re…
ebma Jul 2, 2026
7bb7f0e
refactor(api): enforce taxId match on BRL onramp via shared resolveAv…
ebma Jul 2, 2026
f92232a
fix(api): cap self-serve API keys per user and create pairs atomically
ebma Jul 2, 2026
0426312
fix(frontend): skip BRL limit pre-check for unauthenticated users
ebma Jul 2, 2026
40f55e5
fix(sdk): update Mykobo error mappings to the derived-email server me…
ebma Jul 2, 2026
419b18b
test(api): repair tests left failing by the user-gating behavior changes
ebma Jul 2, 2026
694cf96
improve taxId missmatch error handling
gianfra-t Jul 2, 2026
7bb9c11
Merge branch 'staging' into 1161-sdk-changes-for-alfredpay-currencies…
gianfra-t Jul 2, 2026
92a6254
restore broken tests after merge
gianfra-t Jul 2, 2026
379e51b
Add evaluated USDC to BRLA amount selection logic and related tests
ebma Jul 3, 2026
ddda514
fix(auth): re-pad base64url before decoding JWT expiry
ebma Jul 3, 2026
c773bc1
fix(auth): keep token refresh loop alive when expiry is undecodable
ebma Jul 3, 2026
2ddd5c0
refactor(auth): drop redundant session teardown in refresh actor
ebma Jul 3, 2026
45a42ed
fix(auth): return 503 not 401 for transient refresh failures
ebma Jul 3, 2026
d39c674
Adjust alfredpay limit amounts to correct values
ebma Jul 3, 2026
d6e5bfc
Address PR review: encode manual/standard invariants explicitly in am…
ebma Jul 3, 2026
dcf3c89
Merge pull request #1242 from pendulum-chain/make-rebalancer-quote-twice
ebma Jul 3, 2026
456df09
fix(auth): avoid redundant token read and post-unmount refresh timer
ebma Jul 3, 2026
4bdcabf
Merge pull request #1240 from pendulum-chain/fix/session-token-refresh
ebma Jul 3, 2026
204a93f
Merge branch 'staging' into 1161-sdk-changes-for-alfredpay-currencies…
ebma Jul 3, 2026
9fecb8f
fix(frontend): strip endpoint prefix from user-facing API error messages
ebma Jul 3, 2026
ba2f422
add sentry-user-recognition logic
Sharqiewicz Jul 3, 2026
25ce739
fix(frontend): report 409 ramp conflicts and scrub query from Sentry …
ebma Jul 3, 2026
6240f46
Merge pull request #1228 from pendulum-chain/chore/sentry-phase-2-4
ebma Jul 3, 2026
4248e2b
Rewrite example scripts to pass values from env vars
ebma Jul 3, 2026
c54f4f5
feat(sdk): implement pre-flight balance check for offramps and add In…
ebma Jul 3, 2026
7aaa22c
Slightly adjust examples
ebma Jul 3, 2026
07a5799
feat(sdk): add balance check before permit execution to prevent failures
ebma Jul 3, 2026
22641b9
Add preflight balance checks to some handlers
ebma Jul 3, 2026
178a7d0
Merge branch 'staging' into 1161-sdk-changes-for-alfredpay-currencies…
ebma Jul 3, 2026
0e2ea4d
Update package versions
ebma Jul 3, 2026
1415440
Remove obsolete exampleAlfredpayMexico.ts
ebma Jul 3, 2026
1b9f0cf
Merge pull request #1173 from pendulum-chain/1161-sdk-changes-for-alf…
ebma Jul 5, 2026
5ca4d3e
fix(rebalancer): stop retrying deterministic reverts, stagger squidro…
ebma Jul 5, 2026
258e7c6
Merge pull request #1243 from pendulum-chain/fix/rebalancer-retry-and…
ebma Jul 5, 2026
8109dd9
Add testing strategy document
ebma Jul 5, 2026
1f05352
Gate live/network tests behind RUN_LIVE_TESTS
ebma Jul 5, 2026
10b855f
Add hermetic API test harness
ebma Jul 5, 2026
34cc269
Add HTTP-level auth, ownership and quote-consumption invariant tests
ebma Jul 5, 2026
a12f4a0
Add XState machine tests for ramp and KYC flows
ebma Jul 5, 2026
5a2b18d
Run all test suites in CI with a Postgres service container
ebma Jul 5, 2026
8e79b33
Stop live-test module patches from leaking into other test files
ebma Jul 5, 2026
d84f48b
Add BRL onramp corridor scenario tests through the real PhaseProcessor
ebma Jul 5, 2026
be7ff3f
Add component-test infrastructure and first RTL+MSW component test
ebma Jul 5, 2026
4c42547
Fix cross-file test poisoning found by the test audit
ebma Jul 5, 2026
59be4d8
Extend the component-test foundation with jsdom shims and a fuller fa…
ebma Jul 5, 2026
0ad623a
Add RTL flow tests for the quote forms and the ramp progress page
ebma Jul 5, 2026
4f63f63
Serve a fresh system.account from the fake Substrate node
ebma Jul 5, 2026
71300e3
Add a minimal Playwright E2E suite with a mock wallet, run nightly
ebma Jul 5, 2026
b8d41c9
Add SDK-API contract tests over the BRL onramp corridor
ebma Jul 5, 2026
4a9cf61
Close remaining hermeticity gaps in unit tests
ebma Jul 5, 2026
2e9cf15
Fix cannot-fail assertions and stale fixtures from the test audit
ebma Jul 5, 2026
a72815f
Rebuild the quarantined EUR-onramp validation cases on the Base BRL c…
ebma Jul 5, 2026
26252fb
Rewrite webhook-delivery tests against the current RSA-PSS delivery path
ebma Jul 5, 2026
07b8638
Align the live integration tests with the current ramp API contract
ebma Jul 5, 2026
bf88e3f
Make the XCM dry-run test assert its outcome; drop the dead moonbeam …
ebma Jul 5, 2026
659d06c
Remove self-referential frontend tests that could not detect real bugs
ebma Jul 5, 2026
9430c7c
Record the second test-audit remediation pass in the findings doc
ebma Jul 5, 2026
e5d2d7c
Add coverage for ApiManager network configuration and env overrides
ebma Jul 5, 2026
26d8670
Add feasibility notes for the per-user EURC CCTP settlement contract
ebma Jul 5, 2026
875d0b8
Add partner-facing recovery and responsibility model docs
ebma Jul 5, 2026
e0466ad
Record the multi-agent code-review findings for the 1161 SDK branch
ebma Jul 5, 2026
f511d15
Ignore local credential files and agent-tool artifacts
ebma Jul 5, 2026
48c6c0f
Fix strict template-literal address types in the BRL corridor scenari…
ebma Jul 5, 2026
6047068
Neutralize WEBHOOK_PRIVATE_KEY in tests and make the pre-swap settlem…
ebma Jul 5, 2026
f286b92
Add a mock-leak canary and restore the findByPk patch in the ramp sta…
ebma Jul 5, 2026
fe2fbc1
Pin consumeQuote's atomic status filter with a direct invariant test
ebma Jul 5, 2026
b32a863
Add golden tests for the quote pricing math
ebma Jul 5, 2026
e8ad3de
Add a hermetic MXN Alfredpay onramp corridor scenario
ebma Jul 5, 2026
cef194e
Run the SDK unit tests as part of test:sdk
ebma Jul 5, 2026
8e3f6fe
Make a bare root-level bun test fail fast instead of running stale di…
ebma Jul 5, 2026
f455b49
Gate the api suite on an aggregate coverage ratchet in CI
ebma Jul 5, 2026
4fb996d
Correct stale paths and claims in the testing strategy doc
ebma Jul 5, 2026
9e40ddf
Fix expired-lock takeover in the phase processor and pin processor re…
ebma Jul 5, 2026
ba0ec73
Pin fee immutability with dedicated invariant tests
ebma Jul 5, 2026
8a240e0
Make the remaining hardcoded phase-handler sleeps env-overridable
ebma Jul 5, 2026
e82cbc4
Add a hermetic MXN Alfredpay offramp corridor scenario
ebma Jul 5, 2026
555537d
Document the EUR re-enablement precondition at the kill-switch
ebma Jul 5, 2026
369347a
Notify Slack when the nightly e2e run fails
ebma Jul 5, 2026
16f0db8
Extend the coverage ratchet to every workspace suite
ebma Jul 5, 2026
d2e0e84
Update the testing strategy doc for the new corridor, gates, and proc…
ebma Jul 5, 2026
e7cdbcf
Report zero network fee on direct fiat-to-own-stablecoin corridors
ebma Jul 5, 2026
716ec95
Fix issue with env in tests
ebma Jul 6, 2026
6ccda2d
Exclude non-source code from coverage denominators and re-base the fl…
ebma Jul 6, 2026
54dd110
Add a root test:coverage command with per-area and HTML reports
ebma Jul 6, 2026
b2a986c
Update gitignore
ebma Jul 6, 2026
d7a3b4a
Remove doc pages that don't fit this branch
ebma Jul 6, 2026
0b44599
Extend the fake world for swap-corridor scenarios
ebma Jul 6, 2026
39e53fd
Add BRL offramp corridor scenario with real Nabla swap and subsidy caps
ebma Jul 6, 2026
fefb327
Cover the USD/COP/ARS Alfredpay corridors and the F-001 settlement cap
ebma Jul 6, 2026
903974d
Raise the api coverage floors to 48/59 after the new corridor scenarios
ebma Jul 6, 2026
e6ec001
Test the frontend ramp execution actors and fiatAccount machine
ebma Jul 6, 2026
9ffe25f
Add a full BRL onramp E2E journey
ebma Jul 6, 2026
655d960
Update the testing strategy for the new corridor and journey coverage
ebma Jul 6, 2026
5343203
Fix the dead KYC-invalid branch in the validateKyc actor
ebma Jul 6, 2026
a26cec5
Surface the BRL remaining-limit error instead of routing into KYC
ebma Jul 6, 2026
a8c0215
Close the cross-corridor and entry-point coverage gaps
ebma Jul 6, 2026
28aeeb6
Record final-settlement subsidies in the Subsidy table
ebma Jul 6, 2026
f09a21f
Cover per-currency Alfredpay failure modes and the MXN offramp transi…
ebma Jul 6, 2026
00d87e8
Add SDK contract coverage for the Alfredpay offramp rail
ebma Jul 6, 2026
6ff7699
Add a full USD Alfredpay offramp E2E journey
ebma Jul 6, 2026
c13b6cc
Document the new Alfredpay coverage and the executed integrity-check …
ebma Jul 6, 2026
1227294
Fix Alfredpay offramps never leaving the progress screen
ebma Jul 6, 2026
894502b
Widen subsidies.token from enum to varchar so dynamic symbols record
ebma Jul 6, 2026
ff35fd7
Add regression coverage for subsidy rows with non-enum token symbols
ebma Jul 6, 2026
15788ff
Add a corridor-by-entry-point coverage matrix to the testing strategy
ebma Jul 6, 2026
cd334b1
Add SDK contract coverage for the Alfredpay onramp rail
ebma Jul 6, 2026
41a20ea
Drive the MXN offramp through the SDK contract lifecycle
ebma Jul 6, 2026
af56280
Run the full Alfredpay SDK lifecycle for every currency in both direc…
ebma Jul 6, 2026
1a56cf9
Add the missing COP arrival text on the sell success page
ebma Jul 6, 2026
5dd4873
Wire ARSOnrampDetails into the onramp summary so ARS buyers see the CVU
ebma Jul 6, 2026
b111323
Extend the fake anchors: per-currency payment instructions and Mykobo…
ebma Jul 6, 2026
f5b1a06
Cover the cross-chain leg for every live corridor
ebma Jul 6, 2026
b7fa953
Add hermetic EUR corridor scenarios to meet the re-enablement precond…
ebma Jul 6, 2026
27981b8
Remove the single-currency Alfredpay journeys superseded by the param…
ebma Jul 6, 2026
9f4c09b
Update the coverage matrix for the closed cross-chain, E2E, and EUR gaps
ebma Jul 6, 2026
350a970
Raise the api coverage floors to 55/64 after the corridor and EUR sweep
ebma Jul 6, 2026
2cb6fba
Add the SPEI and ACH payment methods for the live Alfredpay corridors
ebma Jul 6, 2026
2221c97
Document the bank transfer corridors and self-service user API key pr…
ebma Jul 6, 2026
c929e7d
Restructure the api docs around one auth page and one corridors page
ebma Jul 6, 2026
af882bc
Fix the typecheck errors in the Alfredpay corridor and E2E specs
ebma Jul 6, 2026
7067f31
Make the OpenAPI file importable and mark the EUR corridor as live
ebma Jul 6, 2026
fdf97ae
Merge pull request #1244 from pendulum-chain/test-suite-foundation
ebma Jul 6, 2026
2483678
Adjust error message for tax id not linked to profile
ebma Jul 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .agents/skills/sentry-vortex/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
name: sentry-vortex
description: Audit code against Vortex's Sentry conventions and guide correct error instrumentation. Triggers on: sentry, captureException, error reporting, error monitoring, beforeSend, ignoreErrors, adding an API service method, new error class, new XState machine error handling, ErrorBoundary, "is this reported to Sentry".
user-invocable: true
argument-hint: "[files or 'current changes' — defaults to the working-tree diff]"
---

Audit changed code against Vortex's established Sentry conventions and report violations with concrete fixes; also the authority for how to instrument new code correctly.

## MANDATORY PREPARATION

1. Read the canonical implementation so you check against real code, not memory:
- `apps/frontend/src/helpers/sentry.ts`
- `apps/frontend/src/services/api/api-client.ts`
- `apps/frontend/src/machines/ramp.machine.ts`
2. Determine scope: the argument, or `git diff --name-only HEAD` if blank.

---

## Diagnostic Scan

Check each rule. Report a finding only when violated.

### Configuration (single source of truth)
- All filtering lives in `helpers/sentry.ts`. New ignore/deny/scrub logic edits that file — **NEVER** inline new filter config into `Sentry.init` in `main.tsx`.
- `environment: config.env` (never `config.isProd ? ... : ...`). Sampling stays prod-gated.
- Session Replay keeps `maskAllText: true` + `blockAllMedia: true`.

### Error classes
- A custom `Error` whose failures should be filterable by business area **must** `implements DomainError` and set `domain`. API errors derive it from `getApiDomain()` (the source of truth for domain values); non-API errors set it directly (e.g. `SignRampError` → `wallet`).

### API layer (`services/api/`)
- A new top-level path segment (e.g. `/payouts/...`) **must** be added to `getApiDomain()`.
- `ApiError` messages run through `normalizePath()` — **CRITICAL**: never interpolate raw ids/addresses into an error message or Sentry tag; it fragments grouping and can leak PII.

### Capture points
- Money-flow / machine failures are captured at the machine's terminal error state (`captureActorError` pattern), skipping `SignRampError` `UserRejected`.
- **NEVER** call `Sentry.captureException` inside React components, render paths, or fetch/TanStack-Query interceptors — let errors propagate to the machine error state or the global handler.
- Risky subtrees (widget/KYC/ramp) are wrapped in `Sentry.ErrorBoundary` with a fallback.

### Noise & privacy
- `ignoreErrors` covers wallet user-rejections, `ResizeObserver` loops, extension-context errors, `AbortError`. **IMPORTANT**: keep `TimeoutError` reportable — a timeout can mean a slow backend.
- `beforeSend` drops expected client 4xx (`401/403/404/409/429`); `400/422` and all `5xx` are kept.
- No PII in query params, tags, contexts, or messages — `beforeSend` strips query strings, but new code must not route PII somewhere it can't reach.
- **User context**: `Sentry.setUser` is set/cleared only in `AuthService` (plus a startup seed in `main.tsx`) and carries the **pseudonymous Supabase id only** (`{ id: userId }`) — **NEVER** email, wallet, or IP. New auth code must keep this invariant.

## Generate Report

Group findings by file, `file:line`, each with the violated rule and a concrete fix. End with a one-line compliance verdict.

```
## apps/frontend/src/services/api/payouts.service.ts
payouts.service.ts:14 - new "/payouts" segment not mapped in getApiDomain() → add case "payouts": return "ramp"

## apps/frontend/src/components/Foo.tsx
Foo.tsx:88 - Sentry.captureException in a component → remove; let it propagate to the machine Error state

Verdict: 2 violations — not compliant.
```

**NEVER:**
- Report a violation without the exact fix.
- Flag `Sentry.captureException` at the sanctioned capture point (`captureActorError`) as a violation.
- Recommend blanket-ignoring `Failed to fetch` / `NetworkError` / `Loading chunk failed` — monitor volume first.
- Recommend adding `SENTRY_AUTH_TOKEN` or `VITE_ENVIRONMENT` in code — they are Netlify build env vars; flag as infra TODOs only.

## Verify Audit

- Every changed `services/api/`, error class, and XState machine error path was checked.
- Every finding has a `file:line` and a fix.
- No false positives against the sanctioned patterns in the canonical files.

A trustworthy Sentry is one where every reported issue is real and actionable — audit to keep noise out and signal in.
2 changes: 1 addition & 1 deletion .agents/skills/vortex-integration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ try {
## Current corridor reality (May 2026)
- **BRL via PIX**: onramp and offramp both live.
- **EUR via SEPA**: SDK types exist (`EurOnrampQuote`, `EurOfframpQuote`) but handlers throw `"Euro onramp/offramp handler not implemented yet"` at runtime. Treat as `planned`.
- **ARS via CBU**: offramp only.
- **ARS via CBU**: supported via the AlfredPay corridor; route resolver determines availability per-combination.
- **USD / MXN / COP via ACH / SPEI / WIRE**: supported via the AlfredPay corridor; route resolver determines availability per-combination.

## Common failures
Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,56 @@ jobs:

- name: ✏️ Typecheck
run: bun run typecheck

test:
name: Running tests
runs-on: ubuntu-latest
env:
CI: true

services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: vortex_test
ports:
- 54329:5432
options: >-
--health-cmd pg_isready
--health-interval 5s
--health-timeout 5s
--health-retries 10

steps:
- name: 🛒 Checkout code
uses: actions/checkout@v3

- name: 🧩 Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.1

- name: 🧩 Install dependencies
run: bun install --frozen-lockfile

- name: 🔨 Build shared package
run: bun run build:shared

- name: 🧪 Shared tests (coverage-gated)
run: cd packages/shared && bun run test:coverage

- name: 🧪 SDK tests
run: bun run test:sdk

- name: 🧪 SDK coverage gate
run: cd packages/sdk && bun run test:coverage

- name: 🧪 Rebalancer tests (coverage-gated)
run: cd apps/rebalancer && bun run test:coverage

- name: 🧪 API tests (unit + integration, coverage-gated)
run: cd apps/api && bun run test:coverage

- name: 🧪 Frontend tests (coverage-gated)
run: cd apps/frontend && bun run test:coverage
62 changes: 62 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Non-PR-blocking Playwright E2E journeys (see docs/testing-strategy.md).
# Runs nightly and on demand; failures alert but never gate merges.
name: e2e

on:
schedule:
- cron: "0 3 * * *"
workflow_dispatch:

jobs:
e2e:
name: Playwright E2E journeys
runs-on: ubuntu-latest
env:
CI: true

steps:
- name: 🛒 Checkout code
uses: actions/checkout@v3

- name: 🧩 Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.1

- name: 🧩 Install dependencies
run: bun install --frozen-lockfile

- name: 🔨 Build shared package
run: bun run build:shared

- name: 🌐 Install Playwright browsers
working-directory: apps/frontend
run: bunx playwright install --with-deps chromium

- name: 🧪 E2E journeys
working-directory: apps/frontend
run: bun run test:e2e

- name: 📤 Upload report on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: apps/frontend/playwright-report/
retention-days: 7

# Non-blocking runs are only useful if somebody hears about failures.
# Uses the same webhook token the backend's Slack notifier uses
# (repo secret SLACK_WEB_HOOK_TOKEN); skips silently when unset.
- name: 📣 Notify Slack on failure
if: failure()
env:
SLACK_WEB_HOOK_TOKEN: ${{ secrets.SLACK_WEB_HOOK_TOKEN }}
run: |
if [ -z "$SLACK_WEB_HOOK_TOKEN" ]; then
echo "SLACK_WEB_HOOK_TOKEN secret not configured; skipping notification."
exit 0
fi
curl -sf -X POST -H 'Content-Type: application/json' \
-d "{\"text\":\"Nightly Playwright e2e run failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}" \
"https://hooks.slack.com/services/${SLACK_WEB_HOOK_TOKEN}"
76 changes: 74 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ dist
dist-ssr
*.local

# Coverage reports (any workspace; bun/vitest lcov output)
coverage

# Environment files (any package, any name)
**/.env
packages/sdk/.env
**/.env.local
**/.env.*.local
**/.env.development
Expand Down Expand Up @@ -57,5 +60,74 @@ CLAUDE.local.md
# hardhat generated files in workspace contract projects
contracts/*/artifacts
contracts/*/cache
contracts/*/.env

.mcp.json

# Playwright E2E artifacts
apps/frontend/test-results/
apps/frontend/playwright-report/

.mcp.json
# Local credentials and agent-tool artifacts
.api-key.json
.playwright-mcp/
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/interfaces/IERC1363.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/interfaces/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/token/ERC20/utils/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/token/ERC20/ERC20.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/token/ERC20/IERC20.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/token/ERC20/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/token/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/utils/introspection/IERC165.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/utils/introspection/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/utils/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/utils/ReentrancyGuard.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/contracts/index.ts
/contracts/cctp-settlement/typechain-types/@openzeppelin/index.ts
/contracts/cctp-settlement/typechain-types/contracts/interfaces/index.ts
/contracts/cctp-settlement/typechain-types/contracts/interfaces/ITokenMessengerV2.ts
/contracts/cctp-settlement/typechain-types/contracts/mocks/index.ts
/contracts/cctp-settlement/typechain-types/contracts/mocks/MockERC20.ts
/contracts/cctp-settlement/typechain-types/contracts/mocks/MockTokenMessengerV2.ts
/contracts/cctp-settlement/typechain-types/contracts/index.ts
/contracts/cctp-settlement/typechain-types/contracts/PerUserCctpSettlement.ts
/contracts/cctp-settlement/typechain-types/contracts/PerUserCctpSettlementFactory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/interfaces/IERC1363__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/interfaces/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/token/ERC20/utils/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/token/ERC20/utils/SafeERC20__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/token/ERC20/ERC20__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/token/ERC20/IERC20__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/token/ERC20/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/token/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/utils/introspection/IERC165__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/utils/introspection/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/utils/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/utils/ReentrancyGuard__factory.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/contracts/index.ts
/contracts/cctp-settlement/typechain-types/factories/@openzeppelin/index.ts
/contracts/cctp-settlement/typechain-types/factories/contracts/interfaces/index.ts
/contracts/cctp-settlement/typechain-types/factories/contracts/interfaces/ITokenMessengerV2__factory.ts
/contracts/cctp-settlement/typechain-types/factories/contracts/mocks/index.ts
/contracts/cctp-settlement/typechain-types/factories/contracts/mocks/MockERC20__factory.ts
/contracts/cctp-settlement/typechain-types/factories/contracts/mocks/MockTokenMessengerV2__factory.ts
/contracts/cctp-settlement/typechain-types/factories/contracts/index.ts
/contracts/cctp-settlement/typechain-types/factories/contracts/PerUserCctpSettlement__factory.ts
/contracts/cctp-settlement/typechain-types/factories/contracts/PerUserCctpSettlementFactory__factory.ts
/contracts/cctp-settlement/typechain-types/factories/index.ts
/contracts/cctp-settlement/typechain-types/common.ts
/contracts/cctp-settlement/typechain-types/hardhat.d.ts
/contracts/cctp-settlement/typechain-types/index.ts
18 changes: 18 additions & 0 deletions apps/api/bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[test]
# Only discover tests under src/ — the swc build in dist/ contains compiled
# copies of test files that would otherwise run (stale) a second time.
root = "src"
preload = ["./src/test-utils/preload.ts"]

# Coverage report config; the gate itself lives in scripts/check-coverage.ts.
# Excluded from the denominator: built/foreign packages (sdk has its own suite),
# migrations (run-once DDL), and generated contract ABIs (const data, always "covered").
coverageSkipTestFiles = true
coveragePathIgnorePatterns = [
"**/packages/shared/dist/**",
"**/packages/sdk/**",
"**/test-utils/**",
"**/database/migrations/**",
"**/src/contracts/**"
]

5 changes: 4 additions & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@
"seed:phase-metadata": "bun -r @swc-node/register src/database/seeders/phase-metadata.ts",
"serve": "bun dist/index.js",
"start": "bun run build && bun run serve",
"test": "bun test"
"test": "bun test",
"test:coverage": "bun test --coverage --coverage-reporter=lcov && bun ../../scripts/check-coverage.ts coverage/lcov.info 0.55 0.64",
"test:db:start": "./scripts/test-db.sh start",
"test:db:stop": "./scripts/test-db.sh stop"
},
"version": "1.0.0"
}
37 changes: 37 additions & 0 deletions apps/api/scripts/test-db.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# Manages the dedicated Postgres container for integration tests.
set -euo pipefail

CONTAINER=vortex-test-db
PORT="${TEST_DB_PORT:-54329}"

case "${1:-start}" in
start)
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
docker start "$CONTAINER" >/dev/null
else
docker run -d --name "$CONTAINER" \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=vortex_test \
-p "${PORT}:5432" \
postgres:16-alpine >/dev/null
fi
for _ in $(seq 1 30); do
if docker exec "$CONTAINER" pg_isready -U postgres >/dev/null 2>&1; then
echo "test db ready on port ${PORT}"
exit 0
fi
sleep 1
done
echo "test db failed to become ready" >&2
exit 1
;;
stop)
docker rm -f "$CONTAINER" >/dev/null
echo "test db removed"
;;
*)
echo "usage: $0 [start|stop]" >&2
exit 1
;;
esac
Loading
Loading