Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
c6a2cc6
refactor flow routing logic
gianfra-t Jun 8, 2026
cc3d30d
add morpho deposit flow variant
gianfra-t Jun 8, 2026
6eab26b
check for allowance to await for state sync
gianfra-t Jun 9, 2026
d3e17f9
Add vault "token" to UI selector
gianfra-t Jun 9, 2026
8a3a5fa
deposit into destination address, bypass small subsidy cap issue
gianfra-t Jun 9, 2026
264bd01
use morphoDeposit as single phase handler
gianfra-t Jun 9, 2026
7623656
adjust dev command
gianfra-t Jun 11, 2026
9eec84e
add bridge step to morpho demo flow
gianfra-t Jun 11, 2026
295315f
adjust quote service logic
gianfra-t Jun 11, 2026
92ff6d1
test flow
gianfra-t Jun 11, 2026
bb2fd7d
add morpho offramp changes
gianfra-t Jun 12, 2026
d69f35c
adjust morpho offramp to start from any evm
gianfra-t Jun 15, 2026
525707e
better permit execution
gianfra-t Jun 15, 2026
2e7e432
fix bug in nabla minimum output calculation
gianfra-t Jun 15, 2026
5515a7a
adjust morpho flow from non-base networks
gianfra-t Jun 16, 2026
60d0813
adjust squidrouter pay for Morhpo flow
gianfra-t Jun 16, 2026
39ee8d2
adjust final settlement phase for morpho onramp outside Base
gianfra-t Jun 16, 2026
3ec7c68
refactor fund ephemeral handler
gianfra-t Jun 16, 2026
5f9fc34
disable intent mocking
gianfra-t Jun 17, 2026
3795378
use real ip for intent calling
gianfra-t Jun 17, 2026
b32923e
first proposal and refactor
gianfra-t Jun 17, 2026
049c5a1
refactor proposal
gianfra-t Jun 18, 2026
6673c75
update simulation state when subsidizing
gianfra-t Jun 18, 2026
1d3cbac
remove morpho changes
gianfra-t Jun 18, 2026
9dcb75a
remove opencode config
gianfra-t Jun 18, 2026
374bff3
types improvements, re-implement example flow for refactor, invarianc…
gianfra-t Jul 6, 2026
51dab59
Merge branch 'staging' into refactor-phase-composability
gianfra-t Jul 16, 2026
59f8f38
blocks: per-phase prepareTxs — the third leg of the phase contract
gianfra-t Jul 16, 2026
e49e768
blocks: add TYPE-SYSTEM.md walkthrough of the FlowBuilder type system
gianfra-t Jul 16, 2026
3fe45b2
blocks: split phase layers into directories
gianfra-t Jul 17, 2026
72fe5dd
blocks: localize simulation metadata ownership
gianfra-t Jul 21, 2026
4244f39
blocks: add AlfredPay cross-chain flow
gianfra-t Jul 21, 2026
6c87476
blocks: wire flow catalog into production
gianfra-t Jul 21, 2026
e7fdf48
blocks: add direct onramp flows
gianfra-t Jul 22, 2026
76dc391
blocks: extend flow core contracts
gianfra-t Jul 22, 2026
dd4dfcb
blocks: port remaining ramp corridors
gianfra-t Jul 22, 2026
8353b04
blocks: refine cleanup and catalog imports
gianfra-t Jul 22, 2026
579f673
blocks: simplify flow type system to FlowBuilder<O>
gianfra-t Jul 23, 2026
21008cd
Merge branch 'staging' into refactor-phase-composability
gianfra-t Jul 28, 2026
402221b
fix(api): restore block fee and discount parity
gianfra-t Jul 28, 2026
b2b5600
fix(api): restore legacy executor parity
gianfra-t Jul 28, 2026
a66030e
fix(api): isolate block test mocks
gianfra-t Jul 29, 2026
883e7b2
fix(api): restore BRL quote and ramp parity
gianfra-t Jul 29, 2026
5bb671f
test(api): isolate quote parity tests
gianfra-t Jul 29, 2026
ca92453
refactor(api): remove legacy quote and phase pipelines
gianfra-t Jul 29, 2026
4e325ce
feat(api): support mock anchor flows and small subsidies
gianfra-t Jul 29, 2026
04b10d8
fix(api): preserve bridge fees in Avenia offramps
gianfra-t Jul 29, 2026
3892f52
fix(api): use settlement token for Alfredpay limits
gianfra-t Jul 29, 2026
ac20a42
test(api): isolate Mykobo fee simulation mock
gianfra-t Jul 29, 2026
84b991f
Merge pull request #1232 from pendulum-chain/refactor-phase-composabi…
gianfra-t Jul 29, 2026
16293e9
docs: review security spec after block flow refactor
ebma Jul 30, 2026
cb68c74
docs: add second-pass security review feedback
ebma Jul 30, 2026
603363f
feat(api): bind ramps to versioned block flows
ebma Jul 30, 2026
a167e62
fix(api): fail closed on subsidy valuation and caps
ebma Jul 30, 2026
89f0c5a
feat(api): durably claim external financial operations
ebma Jul 30, 2026
a863a97
fix(api): scope webhooks to their owner and harden delivery
ebma Jul 24, 2026
145bbd4
fix(api): require webhook ownership and tighten SSRF checks
ebma Jul 27, 2026
1950814
fix(api): fail closed on indeterminate authentication
ebma Jul 30, 2026
07321ca
fix(api): look up secret keys by identifier prefix instead of bcrypt …
ebma Jul 24, 2026
bb0d85b
feat(api): add legacy API-key digest backfill script
ebma Jul 27, 2026
a629966
fix(api): refuse legacy api key authentication
ebma Jul 30, 2026
e1a83c5
fix(api): fail closed on presigned transaction preflights
ebma Jul 30, 2026
c7731a1
fix(api): propagate phase cancellation through block execution
ebma Jul 30, 2026
3688c52
docs: rewrite fee-integrity spec around the current fee engine
ebma Jul 24, 2026
81766de
fix(api): scope ephemeral freshness to the route and check EVM balance
ebma Jul 24, 2026
567b300
docs(api): sync freshness spec and cover every route branch in tests
ebma Jul 27, 2026
c5ac9fb
fix(clients): retain recovery keys until terminal expiry
ebma Jul 30, 2026
8a06ade
fix(api): cap recipient invite discounts by deployment policy
ebma Jul 30, 2026
2f234f1
fix(relayer): isolate token and native value accounting
ebma Jul 30, 2026
7c18da9
fix(api): persist route-scoped cross-chain evidence
ebma Jul 30, 2026
88aa42f
fix(api): reject unsupported recipient payouts
ebma Jul 30, 2026
3adc34a
fix(api): redact partner mismatch responses
ebma Jul 30, 2026
7d51df7
build(relayer): pin OpenZeppelin contracts
ebma Jul 30, 2026
e19a066
docs: establish authoritative security risk register
ebma Jul 30, 2026
2b57195
fix(api): stabilize durable start operation fingerprints
ebma Jul 30, 2026
dc7ccb0
test(api): align block fixtures with versioned flow metadata
ebma Jul 30, 2026
cb39bd9
test(api): assert ambiguous financial operations halt
ebma Jul 30, 2026
0f34d84
fix(api): halt ambiguous financial operation retries
ebma Jul 30, 2026
4fa991a
test(api): repair post-refactor ramp fixtures
ebma Jul 30, 2026
0928419
fix(api): require explicit rejection for financial retries
ebma Jul 30, 2026
ade2f3c
chore(repo): remove residual stellar and spacewalk references
ebma Jul 30, 2026
8a1d114
refactor(api): centralize financial operation phase context
ebma Jul 30, 2026
c57e1de
fix(api): load env before API key backfill
ebma Jul 30, 2026
59b05d5
feat(api): add API credential pair identifiers
gianfra-t Jul 30, 2026
c3002b5
chore(api): add local stale ramp cleanup
ebma Jul 30, 2026
9703b1a
feat(dashboard): add API key management
gianfra-t Jul 30, 2026
c720687
docs(repo): clarify API key authentication flows
gianfra-t Jul 30, 2026
28b9822
fix(api): preserve structured log metadata
ebma Jul 30, 2026
b5362b6
fix(frontend): refresh SquidRouter progress copy
ebma Jul 30, 2026
9d452a9
feat(api): add authenticated corridor limits
gianfra-t Jul 30, 2026
60faa01
feat(dashboard): add corridor limits page
gianfra-t Jul 30, 2026
6bbe081
fix(api): support TLS certificates in key backfill
ebma Jul 31, 2026
12c5f6c
Merge pull request #1296 from pendulum-chain/codex/security-spec-revi…
ebma Jul 31, 2026
a12eb86
docs(repo): consolidate project documentation
ebma Jul 31, 2026
0b64dbe
docs(repo): align agent documentation rules
ebma Jul 31, 2026
b074f19
docs(repo): repair migrated documentation references
ebma Jul 31, 2026
3cd499f
Merge branch 'staging' into add-limits-and-key-to-dashboard
gianfra-t Jul 31, 2026
8846fc7
docs(repo): flatten documentation structure
ebma Jul 31, 2026
83ef2f4
docs(repo): standardize document filenames
ebma Jul 31, 2026
08c02f5
docs(repo): remove obsolete documentation snapshots
ebma Jul 31, 2026
c3ac73d
Remove PUBLIC-RELEASE-READINESS.md
ebma Jul 31, 2026
a1997e4
fix(api): scope block flow startup validation
ebma Jul 31, 2026
d7afa34
fix(api): enforce ramp start deadline on updates
ebma Jul 31, 2026
fe9439f
Merge pull request #1300 from pendulum-chain/codex/fix-block-flow-sta…
ebma Jul 31, 2026
af44248
fix(api): address credential and limit review findings
gianfra-t Jul 31, 2026
79c75f0
test(api): align SDK secret key error assertion
gianfra-t Jul 31, 2026
e0c0a74
docs: add API credential unification plan
ebma Jul 31, 2026
1f6964f
feat(api): implement API credential unification
gianfra-t Jul 31, 2026
af1ff95
Merge remote-tracking branch 'origin/staging' into add-limits-and-key…
gianfra-t Jul 31, 2026
935255d
Merge pull request #1299 from pendulum-chain/codex/consolidate-projec…
ebma Aug 3, 2026
92d3c2f
Merge remote-tracking branch 'origin/staging' into add-limits-and-key…
ebma Aug 3, 2026
9ad9a5a
docs(api): plan headless managed profiles
ebma Aug 3, 2026
616773f
fix(shared): use Alchemy for Polygon Amoy RPC
ebma Aug 3, 2026
b228085
docs(api): simplify headless profile proposal
ebma Aug 3, 2026
9dbc354
fix(shared): sign destination-phase EVM transactions exactly once
ebma Aug 3, 2026
80c6d26
Merge pull request #1303 from pendulum-chain/claude/fix-evm-destinati…
ebma Aug 3, 2026
02c8603
test(shared): cover Polygon Amoy signing transport order
ebma Aug 3, 2026
9161b2c
Merge remote-tracking branch 'origin/staging' into claude/pr-1301-sec…
ebma Aug 3, 2026
1364cfa
Merge pull request #1302 from pendulum-chain/claude/pr-1301-security-…
ebma Aug 3, 2026
bdc93d9
Merge pull request #1298 from pendulum-chain/add-limits-and-key-to-da…
ebma Aug 3, 2026
69977b5
fix(api): route sell quotes to settlement chains
ebma Aug 3, 2026
70094e5
refactor(api): remove unused rampType from evm bridge requests
ebma Aug 3, 2026
b7fca82
fix(e2e): monitor quotes and serialize auth refresh
ebma Aug 3, 2026
a548a38
fix: address quote and auth review feedback
ebma Aug 3, 2026
58deb1b
fix(api): resolve business provider customers across profile entities
ebma Aug 3, 2026
71b992b
fix(dashboard): preserve superseding auth sessions
ebma Aug 3, 2026
f13c02a
Merge pull request #1304 from pendulum-chain/codex/fix-sell-quotes-wi…
ebma Aug 3, 2026
573c959
fix(api): avoid stray entity on subaccount retry, prefer active entity
ebma Aug 3, 2026
0dfa221
Merge pull request #1305 from pendulum-chain/fix/kyb-business-entity-…
ebma Aug 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
63 changes: 41 additions & 22 deletions .agents/skills/vortex-integration/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: vortex-integration
description: Use when integrating Vortex or @vortexfi/sdk, including quotes, onramps/offramps for BRL (PIX), EUR (SEPA), USD (ACH), MXN (SPEI), COP, and ARS (CBU), ramp register/update/start/status flows, webhook verification, ephemeral key custody, supported corridors, sandbox/production auth, and recovery from ramp errors.
description: Use when integrating Vortex or @vortexfi/sdk, including unified API credentials, sanitized ramp info, quotes, onramps/offramps for BRL (PIX), EUR (SEPA), USD (ACH), MXN (SPEI), COP, and ARS (CBU), ramp register/update/start/status flows, webhook verification, ephemeral key custody, supported corridors, sandbox/production auth, and recovery from ramp errors.
---

# Vortex Integration Skill
Expand All @@ -15,10 +15,12 @@ A machine-loadable capability catalog for AI coding agents integrating Vortex in

- **SDK**: `@vortexfi/sdk` (JavaScript/TypeScript). Install: `npm i @vortexfi/sdk`.
- **API base URLs**: production `https://api.vortexfinance.co`, sandbox `https://api-sandbox.vortexfinance.co`.
- **Auth keys**: partner integrations use a key pair.
- `pk_live_*` / `pk_test_*` — public key, sent in request bodies for partner attribution.
- `sk_live_*` / `sk_test_*` — secret key, sent in the `X-API-Key` header. **Never expose `sk_*` in a browser or mobile app.**
- **Ramp registration requires a user-linked `sk_*` key in every corridor** — the register call is rejected unless the authenticated key resolves to a user account. KYC identity (BRL tax ID, Alfredpay customer, Mykobo customer) is derived from that account, never from request fields.
- **API credentials**: one `api_credentials` resource contains one public value and one secret value for exactly one profile subject, with one environment, expiry, optional partner, and atomic revocation lifecycle.
- `pk_live_*` / `pk_test_*` — public value, sent as `X-Public-Key` for attribution and approved low-sensitivity reads. Quote/widget body `apiKey` remains compatibility transport; if both are present they must match.
- `sk_live_*` / `sk_test_*` — secret value, sent only in `X-API-Key`. **Never expose `sk_*` in a browser or mobile app.** It is returned only when the credential is created.
- If both values are configured, they must belong to the same credential or Vortex returns `403 CREDENTIAL_MISMATCH`. A valid secret may be used without a public value.
- **Ramp registration requires an authenticated profile in every corridor.** The secret credential acts only for its bound profile; raw API clients may instead use that profile's Supabase Bearer session. KYC identity (BRL tax ID, Alfredpay customer, Mykobo customer) is derived from the authenticated profile, never from request fields. Shared dummy/ownerless profiles are invalid.
- Profile-managed credentials use `POST/GET/DELETE /v1/api-credentials` with a Supabase Bearer session. One profile may have at most five active non-expired credentials; revoke by credential ID disables both values atomically with no DELETE body.
- **Decimals**: all amounts are strings. Never parse them through JS `Number` — use `BigInt`, `decimal.js`, or equivalent.
- **Quote TTL**: quotes expire (see `expiresAt`). Re-quote, never reuse stale quotes.
- **Presigned counts**: this is **per ephemeral-signed transaction, not per ramp**. Each transaction an ephemeral key signs must be submitted as 5 presigned variants — 1 primary plus exactly 4 backups with consecutive nonces in `meta.additionalTxs` (`NUMBER_OF_PRESIGNED_TXS = 5`); the API rejects any other backup count. A ramp can contain several ephemeral-signed transactions across its phases. (The SDK builds these for you; only raw-API integrations need to construct them.)
Expand Down Expand Up @@ -47,7 +49,7 @@ triggers:
The first call in any ramp flow. A quote pins the price, fees, and route for a short window (see `expiresAt`). You must hold a non-expired quote to call `registerRamp`.

## Prerequisites
- Valid API key pair (`pk_*` + `sk_*`).
- Optional public credential for attribution; a matching secret credential is required later for ramp operations.
- Known input currency, output currency, amount, and target network.

## SDK recipe
Expand Down Expand Up @@ -84,6 +86,7 @@ const sameQuote = await vortex.getQuote(quote.id);
```bash
curl -X POST https://api.vortexfinance.co/v1/quotes \
-H "Content-Type: application/json" \
-H "X-Public-Key: $VORTEX_PUBLIC_KEY" \
-H "X-API-Key: $VORTEX_SECRET_KEY" \
-d '{
"rampType": "BUY",
Expand All @@ -93,8 +96,7 @@ curl -X POST https://api.vortexfinance.co/v1/quotes \
"inputCurrency": "BRL",
"outputCurrency": "USDC",
"network": "Polygon",
"paymentMethod": "pix",
"publicKey": "'"$VORTEX_PUBLIC_KEY"'"
"paymentMethod": "pix"
}'
```

Expand Down Expand Up @@ -343,7 +345,7 @@ triggers:
```

## When to use
The user wants to ramp USD, MXN, COP, or ARS over their domestic banking rail. These corridors **require a user-linked `sk_*` key**: registration resolves the user's KYC and payment profile from the authenticated account. Partner-scoped keys cannot register ramps here. EVM networks only (no AssetHub).
The user wants to ramp USD, MXN, COP, or ARS over their domestic banking rail. Registration resolves KYC and payment ownership from the secret credential's bound profile; raw API clients may instead use that profile's Bearer session. A technical profile without the user's eligible provider account cannot register that user's ramp. EVM networks only (no AssetHub).

| Fiat | Rail identifier | Payment rail |
|------|-----------------|--------------|
Expand Down Expand Up @@ -402,7 +404,7 @@ The SDK cannot **create** fiat accounts; they are created during onboarding in t
## Common failures
- `MissingAlfredpayOnrampParametersError` / `MissingAlfredpayOfframpParametersError` — `destinationAddress`, `fiatAccountId`, or `walletAddress` missing.
- `AlfredpayOnrampKycRequiredError` — the authenticated user has no approved KYC for the corridor's country.
- `400` "requires an API key linked to a user" on register — the `sk_*` key is partner-scoped, not user-linked. Mint a user key after email OTP sign-in.
- `400` "requires an API key linked to a user" on register — the secret credential is not bound to an eligible profile. Create a profile-managed credential after OTP sign-in or provision a managed profile and issue the credential for that explicit subject.
- `InsufficientBalanceError` — the offramp pre-flight found the source wallet balance below the quote's input amount.

---
Expand Down Expand Up @@ -478,12 +480,14 @@ triggers:
## When to use
First-time integration, environment migration, or when an agent needs to decide where each key may live.

## Key types
| Key | Where it goes | Purpose |
## Credential capabilities
| Value | Where it goes | Purpose |
|-----|---------------|---------|
| `pk_live_*` / `pk_test_*` | Anywhere (browser-safe) | Partner attribution. Sent inside request bodies as `publicKey`. |
| `sk_live_*` / `sk_test_*` (partner-scoped) | Server-side only | Webhook management and partner attribution. Sent as `X-API-Key` header. **Cannot register ramps** unless the key is also linked to a user. **Never** ship to browser/mobile bundles. |
| `sk_live_*` / `sk_test_*` (user-linked) | Server-side only | Required for ramp registration in every corridor; corridor identity (BRL taxId, Alfredpay/Mykobo customer) is derived from the linked account. Minted programmatically after email OTP sign-in; shown once at creation. |
| `pk_live_*` / `pk_test_*` | `X-Public-Key`; browser-safe | Quote/widget attribution and sanitized `getRampInfo()`. It cannot read exact limits, ramp details/history/errors, provider accounts, or mutate ramps/webhooks. |
| `sk_live_*` / `sk_test_*` | `X-API-Key`; server-side only | Authenticated operations as the credential's bound profile and optional partner. Never ship it to browser/mobile bundles. |
| Supabase session | `Authorization: Bearer ...` | First-party profile flows and profile-managed credential lifecycle. |

The public and secret values are not independent records. They are two capabilities of one credential and must share an immutable credential ID. Never pair or migrate values by display name.

## SDK recipe
```js
Expand All @@ -500,13 +504,27 @@ const vortex = new VortexSdk({
For server processes that manage their own ephemeral key storage (e.g. HSM, encrypted DB), set `storeEphemeralKeys: false` and persist via your own mechanism.

## REST fallback
Every authenticated endpoint takes:
- Header: `X-API-Key: sk_<env>_<32chars>`
- Body field: `"publicKey": "pk_<env>_<...>"`
Use:
- `X-Public-Key: pk_<env>_<32chars>` on attribution and approved public reads.
- `X-API-Key: sk_<env>_<32chars>` on sensitive/authenticated endpoints.
- `Authorization: Bearer <Supabase JWT>` on `/v1/api-credentials`.

Create a profile-managed credential with `POST /v1/api-credentials`, list one resource per credential with `GET /v1/api-credentials`, and atomically revoke both values with `DELETE /v1/api-credentials/:credentialId` (no body). The secret is present only in the create response.

Use the sanitized readiness read before a ramp when useful:

```js
const info = await vortex.getRampInfo();
// { corridors: { BR: { kycStatus, canBuy, canSell }, ... } }
```

`GET /v1/ramp-info` accepts public, secret, or session capability, derives the profile from that credential/session, and returns no exact limits, PII, provider IDs, failure reasons, account details, or ramp history.

## Common failures
- `401 Unauthorized` — `X-API-Key` missing, malformed, or wrong environment.
- Mixing keys across environments (`sk_test_*` against prod URL) — always silently fails auth.
- `403 CREDENTIAL_MISMATCH` — public/body/header and secret values are not from one credential. Replace the configured pair; do not retry by dropping ownership checks.
- Mixing keys across environments (`*_test_*` against production or `*_live_*` against sandbox) fails validation.
- `409 CREDENTIAL_LIMIT_REACHED` — the profile already has five active non-expired credentials; revoke an unused credential by ID.
- Browser bundle accidentally including `sk_*` — rotate the key immediately if exposed.

---
Expand Down Expand Up @@ -664,7 +682,7 @@ try {
## Current corridor reality (July 2026)
- **BRL via PIX**: onramp and offramp both live. `taxId` deprecated — derived from the user-linked key.
- **EUR via SEPA (Mykobo)**: onramp and offramp fully implemented in the SDK (`FiatToken.EURC`, rail `"sepa"`), but registration is feature-gated server-side and currently returns `503` "EUR ramps are currently disabled" when the gate is on. Quotes succeed regardless — probe registration, not quoting.
- **USD (ACH) / MXN (SPEI) / COP (ACH) / ARS (CBU)**: onramp and offramp live via the AlfredPay corridor; requires a user-linked `sk_*` key. Route resolver determines availability per-combination.
- **USD (ACH) / MXN (SPEI) / COP (ACH) / ARS (CBU)**: onramp and offramp live via the AlfredPay corridor; registration requires an authenticated user identity. Route resolver determines availability per-combination.
- All corridors deliver to EVM networks; AssetHub is only available for BRL routes.

## Common failures
Expand Down Expand Up @@ -713,7 +731,8 @@ Include this payload (with secrets redacted) in any support ticket.
| `InvalidNetworkError` | Network not in `Networks` enum | Use `discover-supported-corridors` |
| `MissingRequiredFieldsError` / `MissingBrlParametersError` / `MissingBrlOfframpParametersError` | Body field missing | Fill the missing field; do not retry blindly |
| `SubaccountNotFoundError` / `KycInvalidError` | BRL KYC issue | Direct user through KYC; do not retry programmatically |
| `MykoboKycRequiredError` / `AlfredpayOnrampKycRequiredError` | EUR / bank-transfer-corridor KYC issue | Onboard the user via the Vortex app or Widget; do not retry programmatically |
| `MykoboKycRequiredError` / `AlfredpayOnrampKycRequiredError` | EUR / bank-transfer-corridor KYC issue | Onboard or provision the credential's bound profile; do not retry programmatically |
| `VortexSdkError` with `code === "CREDENTIAL_MISMATCH"` | Configured public and secret values belong to different credentials | Load both values from the same credential; never infer pairing by name |
| `AmountExceedsLimitError` | Above KYC tier | Lower amount or upgrade KYC |
| `InsufficientBalanceError` | Offramp pre-flight: source wallet balance below the quoted input | Top up the wallet or lower the amount, then re-register from a fresh quote |
| `EphemeralNotFreshError` / `EphemeralFreshnessCheckError` | Generated ephemeral account was not fresh, or freshness could not be verified | Safe to retry `registerRamp` — the SDK generates new ephemerals each attempt |
Expand Down Expand Up @@ -744,4 +763,4 @@ Contact Vortex support if:
- `getErrorLogs` shows the same error repeating across attempts.
- A `complete` ramp shows no `transactionHash` after 10 minutes.

Always include: `rampId`, environment (sandbox/prod), partner `publicKey`, redacted error logs, and the `transactionHash` if present. **Never** include `sk_*` keys in support communications.
Always include: `rampId`, environment (sandbox/prod), credential ID or safe prefix, redacted error logs, and the `transactionHash` if present. Do not include full `pk_*` or `sk_*` values in support communications.
12 changes: 12 additions & 0 deletions .clinerules/00-project-guidance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Project guidance

Use the repository's canonical agent instructions instead of maintaining a separate
Cline-specific copy:

1. Read the root [`CLAUDE.md`](../CLAUDE.md).
2. Read the nearest app or package `CLAUDE.md` before changing that workspace.
3. Follow the documentation placement and lifecycle rules in
[`docs/README.md`](../docs/README.md).

Do not create memory banks, progress journals, completed implementation plans, or
duplicate architecture documents. Update the existing canonical document and its links.
24 changes: 0 additions & 24 deletions .clinerules/01-general-rules.md

This file was deleted.

13 changes: 0 additions & 13 deletions .clinerules/02-useful-prompts.md

This file was deleted.

7 changes: 0 additions & 7 deletions .clinerules/03-frontend-rules.md

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/contracts.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Non-PR-blocking external API contract checks (see docs/features/contract-tests.md).
# Non-PR-blocking external API contract checks (see docs/operations-testing.md).
# Runs the live halves of the contract suites against the real partner APIs nightly;
# failures alert but never gate merges. The hermetic halves of the same suites run
# in the PR-blocking test job.
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Non-PR-blocking Playwright E2E journeys (see docs/testing-strategy.md).
# Non-PR-blocking Playwright E2E journeys (see docs/operations-testing.md).
# Runs nightly and on demand; failures alert but never gate merges.
name: e2e

Expand Down Expand Up @@ -65,6 +65,15 @@ jobs:
path: apps/dashboard/playwright-report/
retention-days: 7

# Browser journeys mock the API and cannot detect deployment or upstream routing failures.
# Probe both live environments through a cross-chain corridor so BUY and SELL exercise Squid.
- name: 🩺 Live BUY/SELL quote smoke tests
if: always()
working-directory: apps/api
env:
VORTEX_QUOTE_SMOKE_URLS: https://api-staging.vortexfinance.co,https://api.vortexfinance.co
run: bun test src/tests/deployed-quotes.e2e.test.ts

# 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.
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ packages/sdk/.env
**/.env.production
**/.env.staging
!**/.env.example
**/.env

# Editor directories and files
.vscode/*
Expand Down
Loading
Loading