docs: add CONTRIBUTING.md - #402
Open
ranjeet150 wants to merge 38 commits into
Open
ranjeet150 wants to merge 38 commits into
ranjeet150 wants to merge 38 commits into
Conversation
…-Protocol-org#365) * test(api): add tests for upload content-type and size validation Adds tests to verify upload_signature validates content-type against an allowlist (image/png, image/jpeg, image/webp), rejects SVG (XSS vector), and enforces a maximum file size before forwarding to Cloudinary. Tests: - upload_signature_rejects_svg_content_type - upload_signature_rejects_oversized_body - upload_signature_accepts_a_valid_png Closes Octo-Protocol-org#256 * test(api): add tests for payment-status PII stripping Adds tests to verify get_payment_status (public, unauthenticated endpoint) does not leak payer_name or payer_email, while list_payment_link_payments (owner-facing, authenticated endpoint) still includes these details. Tests: - get_payment_status_response_does_not_include_payer_email_or_name - get_payment_status_still_returns_the_fields_a_payer_needs - list_payment_link_payments_owner_view_still_includes_payer_details Closes Octo-Protocol-org#255 * test(api): add tests for audit-log search term length cap Adds tests to verify list_audit_logs rejects oversized search terms before they trigger unindexed ILIKE scans in the database. Length cap is proposed at 100 characters. Tests: - list_audit_logs_rejects_search_term_over_the_length_cap - list_audit_logs_accepts_a_normal_length_search_term Closes Octo-Protocol-org#257 * test(store): add tests for address derivation error distinction Adds tests to verify allocate_address distinguishes between a derivation failure (from the muxed_address_for closure) and a genuinely missing wallet. Derivation failures should return a new AddressDerivationFailed variant, not the misleading NotFound. Tests: - allocate_address_returns_derivation_failed_not_not_found_on_a_bad_closure_result - allocate_address_still_returns_not_found_for_a_genuinely_missing_wallet Closes Octo-Protocol-org#258
…-out and allowlist docs (Octo-Protocol-org#366) - Sponsorship budget (Octo-Protocol-org#261): replace the XOR-folded advisory lock with a per-wallet `FOR NO KEY UPDATE` row lock in try_reserve_sponsored_transaction, and pin the daily cutoff to `date_trunc('day', now(), 'UTC')`. The previous `date_trunc('day', now() AT TIME ZONE 'UTC')` yields a naive timestamp that Postgres re-interprets in the session TimeZone, so a non-UTC session shifted the budget day. - Withdrawal history (Octo-Protocol-org#259): add migration 0021 with a partial unique index on (wallet_id, stellar_tx_hash) for withdrawals (deduping any existing rows first), and make record_withdrawal_transaction idempotent (Ok(None) on conflict), upgrading a prior `failed` row to `confirmed` but never downgrading. - Ingest fan-out (Octo-Protocol-org#260): add list_wallets_page and wallets_due_for_poll_page (keyset on id, same backoff filter); the supervisor now iterates pages of 500 with backpressure instead of materialising every due wallet at once. - Allowlist (Octo-Protocol-org#262): the route already validates via to_base_account; document on Store::add_whitelisted_address that format validation is the caller's responsibility.
…cto-Protocol-org#250) (Octo-Protocol-org#367) * test(api): add pagination tests for webhook deliveries Add tests for paginating webhook delivery history endpoint. Tests: - list_deliveries_paginates_with_a_cursor - list_deliveries_next_cursor_is_null_on_the_last_page - list_deliveries_rejects_an_out_of_range_limit Closes Octo-Protocol-org#247 * test(api): add tests for capped whitelist entries Add tests for enforcing per-wallet cap on withdrawal allowlist size. Tests: - add_address_succeeds_up_to_the_cap - add_address_rejects_once_cap_reached - remove_address_frees_a_slot_under_the_cap Closes Octo-Protocol-org#248 * test(api): add tests for whitelist audit logging Add tests for auditing withdrawal allowlist mutations. Tests: - add_address_writes_an_audit_log_entry - remove_address_writes_an_audit_log_entry - whitelist_audit_entries_never_include_the_full_allowlist_or_secret_material Closes Octo-Protocol-org#249 * test(api): add tests for submit-signed replay protection Add tests for replay protection on submit-signed endpoint. Tests: - submit_signed_returns_the_cached_result_on_an_exact_retry - submit_signed_still_relays_a_genuinely_new_transaction - submit_signed_dedup_is_scoped_per_wallet Closes Octo-Protocol-org#250
…n SSRF check, flag sub-stroop amounts (Octo-Protocol-org#368) - webhooks: route each delivery through octo_resilience::execute (3 attempts, exponential backoff, 20s overall ceiling) instead of a hand-rolled loop. Connection errors, timeouts and 5xx are retried; other non-2xx are not. - webhooks: record the HTTP status and a response-body snippet (streamed, capped at 1 KiB, signature/secret redacted) on every delivery. New migration 0021 adds webhook_deliveries.response_body_snippet with a DB-level size CHECK. - api: expose response_body_snippet on the deliveries endpoint, and honour the validated ?limit= (it was hardcoded to 50). - webhooks: is_safe_url now classifies the WHATWG-normalised host with std::net, unwrapping IPv4-mapped IPv6 via to_ipv4_mapped() and rejecting the unspecified address. Closes the [::ffff:7f00:1] bypass and numeric shorthands like 0, 2130706433 and 0x7f.1. - ingest: to_stroops already rejects more than 7 fractional digits (it never truncated). Pin that with tests and log a warning when a record is skipped for an unparseable amount instead of dropping it silently.
…y_for, single half-open probe (Octo-Protocol-org#369) - ingest: tick (and Ingestor::run) now loops poll_once while pages come back full, bounded by MAX_PAGES_PER_TICK = 10; cursor and mark_polled still advance per page. (Octo-Protocol-org#268) - ingest: operation_index_from_toid decodes Horizon's packed int64 TOID with range checks (ledger, tx order, op order); process() skips-and-logs an implausible TOID instead of defaulting operation_index to 0. (Octo-Protocol-org#267) - resilience: delay_for saturates the exponent, avoids 0*inf NaN, and clamps to max_delay_ms before converting to Duration. (Octo-Protocol-org#269) - resilience: HalfOpen now admits exactly one probe; concurrent callers get CircuitError::Open, and a probe that never reports frees its slot after reset_timeout. (Octo-Protocol-org#270) Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…hdrawals (Octo-Protocol-org#370) * test(api): add validation tests for payment link slugs Add validator function and tests for payment-link slug validation: - Tests for invalid characters rejection - Tests for length boundary checks (3-64 characters) - Tests for reserved word rejection (api, admin, health) - Tests for slug normalization (trim, lowercase) Closes Octo-Protocol-org#252 * test(api): add validation tests for payment link redirect_url scheme Add validator function and tests for redirect_url scheme validation: - Tests for https:// URL acceptance - Tests for http:// URL acceptance - Tests for javascript: scheme rejection - Tests for data: scheme rejection - Tests for invalid URLs rejection - Tests for relative URLs rejection Closes Octo-Protocol-org#253 * test(api): add validation tests for payment intent amount cap Add constant and tests for payment-link intent amount upper bound: - Tests to verify cap is set to 10 billion stroops - Tests for amount positive validation - Tests for amount within bounds - Tests for amount exceeding cap rejection - Tests for cap boundary acceptance - Tests for zero/negative amount rejection Closes Octo-Protocol-org#254 * test(api): add rate limiting tests for withdraw_confirm Add rate limit constants and tests for withdraw_confirm rate limiting: - Define WITHDRAW_CONFIRM_RATE_LIMIT_THRESHOLD (10 attempts) - Define WITHDRAW_CONFIRM_RATE_LIMIT_WINDOW (1 hour) - Tests to verify rate limit threshold is reasonable - Tests to verify rate limit window duration - Tests to verify withdrawal OTP TTL matches - Tests to verify limit allows legitimate retries - Tests for amount formatting helper functions Closes Octo-Protocol-org#251
…tocol-org#245, Octo-Protocol-org#244, and Octo-Protocol-org#243 (Octo-Protocol-org#371) * test(api): add tests for webhook endpoint cap per wallet (issue Octo-Protocol-org#246) Add comprehensive tests for webhook endpoint capping per wallet: - create_webhook_succeeds_up_to_the_cap: verifies up to 10 webhooks can be created - create_webhook_rejects_once_the_per_wallet_cap_is_reached: verifies 11th webhook is rejected - delete_webhook_frees_a_slot_under_the_cap: verifies deletion frees up capacity These tests validate the webhook endpoint limiting mechanism to prevent event fan-out amplification attacks on the outbound worker pool. Closes Octo-Protocol-org#246 * test(api): add tests for apikeys route error consistency (issue Octo-Protocol-org#245) Add comprehensive tests for apikeys route error uniformity: - apikeys_routes_return_identical_error_shape_for_nonexistent_and_unowned_wallet: verifies all three routes (generate_key, get_key, delete_key) return identical 404 responses for both nonexistent and unowned wallets - apikeys_routes_succeed_for_the_true_owner: verifies all three routes succeed for the wallet owner - apikeys_nonexistent_and_unowned_wallet_return_same_error: confirms unowned wallets return 404, not 403, preventing wallet enumeration These tests ensure that the apikeys routes cannot be exploited to enumerate valid wallet IDs by probing for differential error responses. Closes Octo-Protocol-org#245 * test(api): add tests for backup requiring login JWT (issue Octo-Protocol-org#244) Add comprehensive tests for backup endpoint auth requirements: - get_backup_rejects_api_key_even_for_the_owning_wallet: verifies that API keys cannot access the backup endpoint, even for wallet owners - get_backup_succeeds_with_owner_login_jwt: verifies the owner can access their backup with a dashboard login JWT - get_backup_rejects_non_owner_login_jwt: verifies non-owners cannot access the backup endpoint These tests ensure that backup retrieval is restricted to dashboard login only, preventing leaked API keys from exfiltrating password-encrypted backups. Closes Octo-Protocol-org#244 * test(api): add tests for consolidated list-endpoint limit validation (issue Octo-Protocol-org#243) Add comprehensive tests for shared limit validation across list endpoints: - validated_limit_rejects_zero_and_negative: verifies limit=0 and negative limits are rejected across wallets and addresses list endpoints - validated_limit_rejects_above_max: verifies limits above the maximum (1000) are rejected - validated_limit_defaults_when_absent: verifies requests without a limit parameter use the default value - list_wallets_respects_limit_validation: regression test for wallets list - list_addresses_respects_limit_validation: regression test for addresses list - list_payment_links_respects_limit_validation: regression test for payment links - list_sponsored_transactions_respects_limit_validation: regression test for sponsored transactions These tests ensure consistent limit validation across all list endpoints, preventing divergent bounds that could lead to security or performance issues. Closes Octo-Protocol-org#243
* test(api): validate JWT_SECRET minimum length at startup Add validation and tests to ensure JWT_SECRET is at least 32 bytes, preventing trivial token forgery attacks that exploit weak HMAC keys. Closes Octo-Protocol-org#242 * test(api): block reserved usernames to prevent impersonation Add validation and tests to prevent users from claiming reserved usernames like 'admin', 'root', 'api', etc., preventing impersonation of system roles. The check is case-insensitive to prevent 'Admin' from bypassing 'admin'. Closes Octo-Protocol-org#241 * test(api): enforce password and credential validation security Add comprehensive tests for credential validation: - Passwords must be at least 8 characters (prevents weak passwords) - Email validation enforces minimum format requirements - Tests ensure no regressions in security-critical validation paths Closes Octo-Protocol-org#240 * test(api): validate token security and deny-list handling Add comprehensive tests for token security: - Each token gets a unique jti to prevent collision attacks - Tokens have a proper 7-day TTL from issue time - Token hashing for deny-list storage is deterministic and collision-resistant - Token verification rejects malformed tokens and wrong signatures - Ensures tokens signed with different secrets are rejected Closes Octo-Protocol-org#227
…nt-link confirmation, case-insensitive slugs (Octo-Protocol-org#373) * fix(store): clamp list limits, idempotent payment confirmation, case-insensitive slugs, insert-only API key - clamp_limit(): every list_* method caps LIMIT at MAX_LIST_LIMIT (1000) as defense in depth beneath the API layer's own validation (Octo-Protocol-org#280). - confirm_payment_link_payment / mark_payment_link_payment_mismatched are guarded by status = 'pending' and return whether the row actually flipped (Octo-Protocol-org#282). - create_payment_link lowercases the slug; get_payment_link_by_slug matches case-insensitively (Octo-Protocol-org#281). - create_api_key: atomic insert-only key creation, Conflict if one already exists (Octo-Protocol-org#279). * fix(store): enforce case-insensitive uniqueness on payment-link slugs Backfills existing slugs to lowercase (oldest row in a case-only collision keeps the slug, newer rows are renamed to <slug>-<id hex>), adds a lowercase CHECK and a lower(slug) unique index. * fix(ingest): fire payment-link webhooks only when the payment row actually transitions A reprocessed deposit, retry, or race with the expiry sweep no longer re-fires payment_link.paid / payment_link.mismatched. * fix(api): require explicit confirmation before rotating an existing API key generate_key silently replaced a wallet's existing API key on every call, so a single accidental retry could break every integration using the old key. Rotation now requires {"confirm": true}; without it an existing key yields 409. First-time generation needs no body.
… balances timeout (Octo-Protocol-org#374) - store: document daily_budget_stroops semantics (None = unlimited, Some(0) = sponsorship disabled today) and enforce them explicitly in try_reserve_sponsored_transaction; a non-positive budget or fee is refused before touching the database (fail closed). - api: reject a per_tx_fee_cap_stroops larger than daily_budget_stroops in put_config with a 400 that names both values. - store: create_otp now supersedes any prior unconsumed OTP for the same (user, purpose) in the same transaction, serialized per pair with an advisory lock, making the at-most-one-live-OTP invariant explicit. - store: verify_and_consume_otp consumes with a conditional UPDATE so concurrent correct submissions can't both succeed and the attempt limit holds under racing guesses. - api: scope a 10s caller-facing timeout to GET /v1/wallets/:id/balances, returning a 504 envelope instead of holding the connection across slow Horizon retries. Closes Octo-Protocol-org#277 Closes Octo-Protocol-org#276 Closes Octo-Protocol-org#275 Closes Octo-Protocol-org#278 Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…pare, escaped emails (Octo-Protocol-org#375) - feat(server): drain in-flight HTTP requests and the current ingest tick on SIGTERM/SIGINT, bounded by SHUTDOWN_DRAIN_TIMEOUT_SECS (default 25) before forcing exit. Previously the process exited immediately, which could drop requests or cut an ingest page mid-way. - fix(migrate-keys): persist the after_id cursor to a checkpoint file (bound to a fingerprint of the key pair) after each completed batch, resume from it on restart, log per-batch progress, and remove it on clean completion. Also reject --batch-size <= 0, which made the tool report "complete" without migrating anything. - fix(store): compare OTP code hashes with subtle::ConstantTimeEq instead of a short-circuiting string inequality. - fix(email): HTML-escape every externally sourced value (email address, asset code, destination, tx hash, failure reason) before interpolating it into templates. Closes Octo-Protocol-org#271 Closes Octo-Protocol-org#272 Closes Octo-Protocol-org#273 Closes Octo-Protocol-org#274 Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…l-org#223-226) (Octo-Protocol-org#376) * test(store): ERC-20 token registry tests Per-chain token registry becomes the single authority on what Octo credits. Tests verify decimals validation, address normalization, symbol spoofing prevention via contract-address matching, and registry lookups. - Test decimals mismatch rejection against on-chain value - Test disabled/unregistered token handling and quarantining - Test address normalization (case insensitive) - Test symbol spoofing prevention (two contracts, same symbol, distinct entries) - Test Stellar asset path resolution preserved - Test CAIP-19 keying and admin-only registration Refs Octo-Protocol-org#223 * test(api): EVM signed-transaction relay tests Non-custodial core: client signs locally, Octo validates, relays, and records. Mirrors Stellar's /submit-signed contract — never a blind signing oracle. Tests verify: - Chain ID enforcement (EIP-155 replay protection) - Sender recovery and authorization check - ERC-20 calldata decoding for recipient validation - Unregistered token rejection - Withdrawal allowlist enforcement - Amount limits - Revert-reason decoding Malformed-input tests cover truncated RLP, oversized bodies, deeply nested structures, and unknown transaction types — all must reject cleanly (400), never panic (500). Refs Octo-Protocol-org#225 * test(api): EVM nonce management and transaction lifecycle tests Server-originated transactions need strictly sequential nonces. One stuck transaction halts every later one on the account. Allocation uses row-level locking (same pattern as muxed-id allocation) to keep nonces gap-free. Tests verify: - Parallel nonce allocation produces sequential, gap-free sequences - Startup reconciliation with eth_getTransactionCount (latest and pending) - Transaction state machine (pending → submitted → mined → confirmed) - Replacement at same nonce with +12.5% gas for underpriced transactions - Gas price cap enforcement (prevents escalation loop during gas spike) - Drop detection and resubmission - Nonce-gap recovery via 0-value self-transfer - Replacement chain recording (both hashes resolve to one logical tx) - eth_feeHistory for gas pricing - Metrics and alerts for stuck transactions and replacements Replacement resubmits at the same nonce, safe because the nonce makes it mutually exclusive with the original — documented to prevent misreading as a submit-asymmetry violation. Refs Octo-Protocol-org#226 * test(wallet): EVM deposit sweep engine tests Per-customer EOAs mean funds must be consolidated into a treasury (Stellar muxed model never required this). Sweeps are gas-funded then executed as a two-step, persisted-intent state machine that reconciles on restart — a crash between funding and sweep cannot double-send or strand funds. Tests verify: - Confirmed deposits sweep to treasury, balance increases exactly - Crash recovery between gas funding and sweep (idempotency) - Economic gating (dust below configurable gas-to-value threshold) - Idempotency: concurrent sweeper runs yield one sweep - Unconfirmed deposits never swept - Failure path: reverted sweep leaves funds safe - Batch sweeping accumulates dust below threshold - State machine transitions (pending → gas_funded → submitted → confirmed) - Startup reconciliation (non-terminal sweeps checked against chain) - Gas-funding tx and sweep tx recording - Metrics: unswept balance, blocked sweeps, stuck sweeps - Per-chain threshold configuration (L1 vs Base vs others) Reuses nonce management from Octo-Protocol-org#226 (no parallel allocator). Requires sweeper to hold derived keys for deposit addresses. Refs Octo-Protocol-org#224
…otocol-org#287, Octo-Protocol-org#288, Octo-Protocol-org#289, Octo-Protocol-org#290) (Octo-Protocol-org#377) * fix(store): make ON DELETE behaviour for every wallet-referencing foreign key explicit Several tables referenced wallet_id with cascade delete behaviour. Documents the current state per table and makes the intended RESTRICT behaviour explicit, so a future wallet-deletion feature can't silently orphan or cascade rows by accident. Closes Octo-Protocol-org#287 * fix(api): reconcile sponsored transactions stuck pending after a crash A process crash between reserving a sponsorship's budget and finalizing it left the row permanently pending, silently consuming budget with no recovery path. Adds a periodic sweep that reconciles stale pending rows past a generous timeout. Closes Octo-Protocol-org#288 * fix(wallet-core): reject transaction XDR with trailing bytes after the envelope XDR decoding across this crate didn't confirm the entire input was consumed, so trailing bytes after a valid envelope passed through silently. Adds a strict decode helper used at every XDR-decoding call site in wallet-core. Closes Octo-Protocol-org#290 * fix(wallet-core): pre-flight the inner transaction's sequence number before signing a fee-bump A stale inner-transaction sequence was only ever caught by Horizon's own rejection after signing and reserving budget. Adds an earlier explicit check so a doomed submission never consumes a signature or a budget reservation. Closes Octo-Protocol-org#289
…ol-org#286, Octo-Protocol-org#283, and Octo-Protocol-org#284 (Octo-Protocol-org#378) * fix(api): validate the audit-log category filter against the known category set An unrecognized category filter value silently returned zero rows, indistinguishable from a genuinely empty result. Validates the filter against the known category constants and returns a clear 400 listing valid values on a mismatch. Closes Octo-Protocol-org#285 * fix(api): support filtering transactions by direction server-side list_transactions returned deposits and withdrawals interleaved with no server-side direction filter, forcing dashboard clients to fetch everything and filter client-side, which breaks pagination math. Adds a validated direction query parameter pushed into SQL. Closes Octo-Protocol-org#286 * fix(api): close any window where a client-custody wallet could be created without verified ownership Audits and hardens the challenge-sign-verify-create sequence for client-custody wallet creation, ensuring create_wallet cannot succeed without an ownership signature it independently verifies. Closes Octo-Protocol-org#283 * fix(store): add a covering index for the ingest poll-scheduling query wallets_due_for_poll runs on every supervisor tick for every network with no confirmed covering index, risking a sequential scan that worsens as wallet count grows. Adds the minimal index(es) needed, created concurrently. Closes Octo-Protocol-org#284 --------- Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…on, and zeroization (Octo-Protocol-org#379) * fix(wallet-core): validate the BIP-39 checksum, not only wordlist membership from_phrase's mnemonic validation needs confirmation that it checks the BIP-39 checksum bits, not merely that each word exists in the wordlist. A checksum-invalid but wordlist-valid phrase is very likely a typo or corrupted backup and must be rejected with a distinguishable error. Closes Octo-Protocol-org#293 * fix(wallet-core): reject an out-of-range derivation index instead of producing an undefined result derive_ed25519_secret accepted a full u32 index for SEP-0005 hardened derivation, which is only well-defined below 2^31. Adds an explicit bounds check so an out-of-range index fails loudly instead of silently deriving a nonsensical or colliding key. Closes Octo-Protocol-org#294 * fix(wallet-core): make StellarNetwork::parse and its callers fail closed on an unrecognized network Confirms and hardens StellarNetwork::parse against any wildcard/default fallback for an unrecognized network string, and audits callers for a silent default-on-None pattern that would defeat the fail-closed guarantee. A misconfigured network must abort startup, not silently sign against the wrong one. Closes Octo-Protocol-org#291 * fix(wallet-core): guarantee decrypted seed zeroization on every signing-function error path Audits sign_payment/sign_change_trust/sign_fee_bump for any early-return path between seed decryption and function exit that could leave secret bytes without a Drop-guaranteed zeroize, and closes any gap found. Adds explicit regression tests for the property per function. Closes Octo-Protocol-org#292
…ayment-link flow, audit taxonomy (Octo-Protocol-org#380) * test(store): cover concurrent gas-tank provisioning and poll backoff tiers set_gas_tank's WHERE guard defends against concurrent double-provisioning but had no test exercising concurrent calls; adds one (8 racers, exactly one wins, the rest get Conflict). wallets_due_for_poll's active/idle/dormant backoff lived in one dense SQL CASE with no boundary coverage; adds tests for the never-polled case, both tier boundaries, and an idle wallet polled within vs past its interval. Closes Octo-Protocol-org#327 Closes Octo-Protocol-org#328 * docs(api): document the payment-link checkout flow and audit-log taxonomy Adds an end-to-end payer curl sequence (get link, intent, signing-info, submit, status) to docs/api.md, and a new docs/audit-log.md cataloguing every audit category, all 13 audit::record call sites, and the convention for adding a new one. Linked from README. Closes Octo-Protocol-org#329 Closes Octo-Protocol-org#330 --------- Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…s a CSPRNG (Octo-Protocol-org#381) provision_wallet's mnemonic generation depended transitively on tiny-bip39's Mnemonic::new, which draws entropy from rand::thread_rng() only when the crate's default `rand` feature is enabled. Generate the 128-bit entropy from OsRng explicitly and build the mnemonic with Mnemonic::from_entropy, so the guarantee no longer rests on a dependency default. Documents the source on WalletSeed::generate, in Cargo.toml and in docs/architecture.md, and adds a collision smoke test. Closes Octo-Protocol-org#319 Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…ol-org#382) add_trustline was a 410 stub. It now validates the asset code, issuer and limit with wallet-core's shared validate_change_trust (also used by the ChangeTrust test signer) and returns what a client needs to build and sign the ChangeTrust locally: sequence, network passphrase, base fee and limit. This follows the same non-custodial build-then-sign-locally pattern as payments and fee-bumps, and the server never signs. Closes Octo-Protocol-org#321 Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…ions (Octo-Protocol-org#383) There was no way for an authenticated user to change their password. Adds POST /v1/auth/change-password, which re-verifies the current password and invalidates every session issued before the change. Each JWT now carries the user's session_epoch, the epoch is bumped atomically with the password hash, and authenticate checks both the epoch and the deny-list in one query. The endpoint is rate-limited per IP (like login) and per user. Closes Octo-Protocol-org#322
…nterruption-safe (Octo-Protocol-org#384) Audit: reseal_wallet writes all four sealed fields in one UPDATE, so a single row is atomic. The audit also found that migrate-keys could not rotate anything. It selected rows with sealed_scheme <> V1, but every record is V1 whichever key sealed it, so a MASTER_KEY -> MASTER_KEY_NEXT run migrated nothing and still reported "0 remaining". Legacy scheme-0 rows failed in open(). While MASTER_KEY_NEXT was set, the server also opened every V1 row with the next key, which broke gas tanks that had not been migrated. - migrate-keys pages over all sealed rows and skips rows that already open under the new key; others are resealed from the old key. The loop moves into a library so tests can run it. - reseal_wallet's guard is now a compare-and-swap on the old ciphertext, since the scheme does not change on a key rotation. - reseal accepts legacy scheme-0 records (same algorithm) and upgrades them to V1. - The server tries MASTER_KEY_NEXT first and falls back to MASTER_KEY when opening, and seals new gas tanks under the next key during a rotation. - Adds interruption tests that crash a run mid-batch, then assert every row is wholly old or wholly new and that a second run finishes the rest. Closes Octo-Protocol-org#320 Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…nks authz matrix (Octo-Protocol-org#387) * feat(api): add a read endpoint for gas-tank status There was no dedicated read endpoint for a wallet's gas-tank status, forcing a dashboard to either lack this data or infer it awkwardly from other responses. Adds a focused GET route returning the tank's account, provisioning state, and today's budget spend. * test(api): add an authorization matrix for every payment-links route payment_links.rs mixes owner-authenticated and fully-public routes with no consolidated authorization regression test, unlike other route groups already covered by authz_matrix_tests.rs. Extends the same matrix pattern to this file. * feat(api): add a forgot-password flow via emailed OTP There was no recovery path for a user locked out of their account. Adds a request/confirm password-reset pair reusing the existing OTP infrastructure, with the same account-enumeration protection already established for login/signup. * feat(api): add an OTP-gated email-change flow There was no way to change a user's login email. Adds a two-step request/confirm flow that verifies control of the new address via OTP before applying the change, so a typo or attacker-supplied address can't silently take over the account's login identity. --------- Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…, Octo-Protocol-org#354, Octo-Protocol-org#352 across api and wallet-core (Octo-Protocol-org#388) This commit simultaneously addresses 4 issues across octo-api and octo-wallet-core: 1. Issue Octo-Protocol-org#348: Request-Body Size Limits Uniformity on Mutating Routes - Audited router wiring in crates/api/src/lib.rs and confirmed that DefaultBodyLimit::max(REQUEST_BODY_LIMIT) (64 KiB) is applied uniformly to the router containing all mutating routes. - Exposed pub const REQUEST_BODY_LIMIT: usize = 64 * 1024 from crates/api/src/lib.rs. - Added a parametrized integration test every_mutating_route_rejects_an_oversized_body_with_a_clean_413 in crates/api/tests/body_size_limit_tests.rs covering every mutating route with oversized payloads asserting clean 413 Payload Too Large responses. - Closes Octo-Protocol-org#348 2. Issue Octo-Protocol-org#350: Sourced BIP-39 Checksum-Invalid Test Vectors - Added a permanent, cited corpus of checksum-invalid BIP-39 mnemonics in crates/wallet-core/src/derive.rs. - Sourced authoritative vectors from Trezor reference implementation (tests/test_mnemonic.py) as well as official BIP-39 specification test vectors (bitcoin/bips/bip-0039.mediawiki and trezor/python-mnemonic/vectors.json) by mutating the final checksum word to alternative valid wordlist entries (almost-valid vectors across 12, 15, 18, and 24-word phrases) alongside grossly invalid vectors. - Added regression test from_phrase_rejects_every_sourced_checksum_invalid_vector parametrized across the corpus to ensure wordlist-and-checksum validation is permanently upheld. - Closes Octo-Protocol-org#350 3. Issue Octo-Protocol-org#354: Public validate_seed_phrase Helper - Extracted mnemonic syntax, wordlist, and checksum validation logic into a public helper function pub fn validate_seed_phrase(phrase: &str) -> Result<(), WalletError> in crates/wallet-core/src/derive.rs. - Re-exported validate_seed_phrase from crates/wallet-core/src/lib.rs. - Refactored WalletSeed::from_phrase to call validate_seed_phrase internally so pre-flight validation and seed construction never diverge. - Documented that validate_seed_phrase is safe for untrusted input and produces no secret material. - Added regression tests verifying agreement between validate_seed_phrase and from_phrase on both valid and invalid vectors, as well as a type-level test proving no secret material is returned. - Closes Octo-Protocol-org#354 4. Issue Octo-Protocol-org#352: Document SEP-0005 Derivation Path and Hardened-Index Invariant - Expanded doc comment on derive_ed25519_secret in crates/wallet-core/src/derive.rs adhering to the project documentation register in CONTRIBUTING.md. - Explicitly documented the exact derivation path (m/44'/148'/index'), the security justification for full hardening on Ed25519 (SLIP-0010) in contrast to EVM BIP-44 unhardened derivation, and the 2^31 hardened-index ceiling. - Cross-referenced docs/deposit-model.md detailing how index 0 underpins the muxed-address architecture. - Added a runnable doc-test example demonstrating correct derivation. - Closes Octo-Protocol-org#352 Co-authored-by: ���feyisaralawal <����feyisaralawal01@gmail.com> Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…-org#389) Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…Protocol-org#390) Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
… sponsor negative tests (Octo-Protocol-org#391) This commit resolves issues Octo-Protocol-org#336, Octo-Protocol-org#334, Octo-Protocol-org#341, and Octo-Protocol-org#337: 1. Readiness endpoint distinct from liveness (Closes Octo-Protocol-org#336) - Added GET /health/ready endpoint in crates/api/src/lib.rs distinct from the cheap GET /health liveness probe. - Implemented Store::ping in crates/store/src/lib.rs executing a lightweight SELECT 1 against the Postgres connection pool. - Implemented Horizon::check_reachability in crates/api/src/horizon.rs probing the root endpoint with a 3-second timeout. - Returns HTTP 200 with structured JSON (status: ready, database: ok, horizon: ok) when all dependencies are healthy. - Returns HTTP 503 with structured JSON naming failed dependencies when degraded. - Added documentation in docs/architecture.md covering liveness vs readiness semantics for orchestrators. - Added integration tests covering reachable 200 and degraded 503 scenarios for DB and Horizon. 2. Shared cursor pagination helper (Closes Octo-Protocol-org#334) - Extracted keyset cursor pagination query construction into cursor_pagination_query(table, filter_column) in crates/store/src/lib.rs. - Refactored list_wallets_for_user_page, list_addresses_page, list_transactions_page, and list_payment_links to use the shared helper, eliminating SQL query drift while preserving exact pagination semantics. - Added isolated unit test in crates/store/tests/store_tests.rs asserting query shape and keyset comparison invariants. 3. Documented rate limit reference table (Closes Octo-Protocol-org#341) - Extracted rate limit thresholds and windows into public named constants in crates/api/src/rate_limit.rs. - Updated crates/api/src/auth.rs and crates/api/src/routes/payment_links.rs to reference the centralized constants. - Added comprehensive reference table to docs/api.md detailing every limited endpoint, HTTP method, key scope (per-IP, per-user), limit, window, and code constant name. - Included process note mandating updates to the table for future rate limit additions. 4. Negative-path coverage for sponsor endpoint (Closes Octo-Protocol-org#337) - Added focused negative-path integration tests in crates/api/tests/sponsor_e2e_tests.rs: - sponsor_rejects_when_sponsorship_is_disabled_for_the_wallet (HTTP 403) - sponsor_rejects_a_max_fee_above_the_per_tx_cap (HTTP 400) - sponsor_rejects_a_self_sponsoring_inner_transaction (HTTP 400) - sponsor_rejects_once_the_daily_budget_is_exhausted (HTTP 429) - sponsor_rejects_for_a_client_custody_wallet_with_no_gas_tank (HTTP 403) - Added create_wallet_without_gas_tank helper to reliably exercise the client-custody unprovisioned gas tank rejection path. Co-authored-by: ���feyisaralawal <����feyisaralawal01@gmail.com> Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…Bruno CI integration (Octo-Protocol-org#392) This commit resolves 4 issues across the store, API, tests, and CI workflows: 1. Webhook delivery failure rollup (Closes Octo-Protocol-org#342) - What was done: Added health rollup metrics (recent_failure_count and last_successful_delivery_at) to each entry in GET /v1/wallets/:id/webhooks without N+1 queries. - How it was done: - Defined WebhookDeliveryHealth in crates/store/src/models.rs. - Added webhook_delivery_health and wallet_webhook_delivery_health in crates/store/src/lib.rs. wallet_webhook_delivery_health executes a single aggregate query grouping by endpoint ID with a bounded 24-hour window for failures and MAX delivery timestamp for successes. - Updated WebhookView in crates/api/src/routes/webhooks.rs with recent_failure_count and last_successful_delivery_at, populated via wallet_webhook_delivery_health. - Added unit/integration tests covering recent failure count, healthy endpoints, and non-N+1 batched queries. 2. Wallet archival lifecycle path (Closes Octo-Protocol-org#345) - What was done: Implemented a non-destructive archival path allowing merchants to retire wallets without losing historical audit trails, hiding archived wallets by default while preserving read access and rejecting mutations. - How it was done: - Created migration crates/store/migrations/0025_archive_wallets.sql adding archived_at TIMESTAMPTZ and index to wallets. - Added archived_at and is_archived() to Wallet in crates/store/src/models.rs. - Added StoreError::WalletArchived mapped to ApiError::Forbidden("wallet is archived"). - Added archive_wallet, unarchive_wallet, and ensure_wallet_active to Store. - Updated list_wallets_for_user with include_archived filter flag (defaulting to false). - Added PATCH /v1/wallets/:id/archive and PATCH /v1/wallets/:id/unarchive endpoints requiring dashboard authentication. - Wired active wallet guards into mutating operations (create_address, submit_signed, withdrawal OTP endpoints, sponsor, and put_config) while keeping read routes accessible. - Added store tests for listing exclusion, mutation rejection, historical read access, and unarchive restoration. 3. Sponsorship budget concurrency load test (Closes Octo-Protocol-org#346) - What was done: Added a gated concurrency load test validating that sponsorship budget reservation stays strictly within daily limits under 100 concurrent callers, tracking latency percentiles. - How it was done: - Implemented sponsorship_budget_reservation_under_100_way_concurrency_never_exceeds_budget in crates/store/tests/store_tests.rs. - Gated behind #[ignore] so it does not slow down the standard test suite. - Spawns 100 concurrent try_reserve_sponsored_transaction tasks against a wallet at its budget limit, measures per-request latency, asserts zero oversubscription, and logs p50/p95/p99 latency percentiles. 4. Bruno API test collection CI runner (Closes Octo-Protocol-org#339) - What was done: Wired the Bruno API test collection and challenge-signing scripts into an automated, non-interactive integration test target for local dev and CI. - How it was done: - Added @usebruno/cli to api-tests/scripts/package.json devDependencies. - Added just test-integration recipe in justfile that compiles the server, starts octo-server, waits for health readiness, runs bru run api-tests --env Local, and cleans up the server process. - Added an integration-test job in .github/workflows/ci.yml running against PostgreSQL service container. - Documented integration and load test execution and environment variables in CONTRIBUTING.md. Co-authored-by: ���feyisaralawal <����feyisaralawal01@gmail.com> Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…-Protocol-org#353, and Octo-Protocol-org#338 across store, crypto, and wallet-core (Octo-Protocol-org#393) Comprehensive multi-issue resolution implementing migration decision documentation, muxed address property-based round-trip testing, cryptographic nonce-uniqueness guarantees, and soft-delete semantics for webhook endpoints. 1. Issue Octo-Protocol-org#349: Migration Decision Index & Foreign Key Audit - Created `docs/migrations.md` providing a one-line-per-migration decision index spanning all 21 append-only migrations in `crates/store/migrations/`. - Documented schema changes, constraint rationale, and foreign key ON DELETE behaviors across tables. - Added explicit cross-reference to the webhook delivery cascade audit (Issue Octo-Protocol-org#338). - Updated `docs/architecture.md` with links to `docs/migrations.md`. - Added convention note to `CONTRIBUTING.md` requiring every future migration PR to update the index in `docs/migrations.md`. Closes Octo-Protocol-org#349 2. Issue Octo-Protocol-org#351: Proptest Round-Trip Corpus for Muxed Address Encoding - Added property-based tests in `crates/wallet-core/src/address.rs` using proptest with 1,000 cases across the full u64 id range. - `encode_then_decode_muxed_round_trips_for_arbitrary_u64_ids`: asserts arbitrary u64 IDs round-trip accurately through encode_muxed and decode_muxed. - `decoded_base_account_always_matches_the_original_input_account`: verifies that the recovered base account matches the initial input account across all ids. Closes Octo-Protocol-org#351 3. Issue Octo-Protocol-org#353: Nonce-Uniqueness & Input-Independence Regression Suite - Added `seals_of_same_plaintext_never_repeat_nonce` in `crates/crypto/src/lib.rs` asserting 10,000 AES-256-GCM seals of the same plaintext under the same key never produce colliding nonces. - Added `nonces_show_no_correlation_with_varying_plaintext_and_key_across_a_large_sample` generating 10,000 seals with randomized master keys and plaintexts. - Computed Pearson correlation coefficients between nonce bytes and key/plaintext inputs, verifying no gross statistical correlation (|r| < 0.05) exists. Closes Octo-Protocol-org#353 4. Issue Octo-Protocol-org#338: Webhook Endpoint Soft-Deletion to Preserve Delivery Audit Logs - Audited foreign key behavior: previously, `webhook_deliveries.endpoint_id` referenced `webhook_endpoints(id) ON DELETE CASCADE`, causing hard deletes to destroy historical delivery logs. - Added migration `0021_soft_delete_webhook_endpoints.sql` introducing `deleted_at TIMESTAMPTZ` and partial index `idx_webhook_endpoints_active_not_deleted`. - Updated `WebhookEndpoint` struct in `crates/store/src/models.rs` with `deleted_at`. - Updated `active_webhook_endpoints` in `crates/store/src/lib.rs` to filter out soft-deleted endpoints (`deleted_at IS NULL AND active = true`), ensuring `dispatch` skips retired endpoints. - Added `delete_webhook` and `list_webhooks(wallet_id, include_deleted)` in `crates/store/src/lib.rs`. - Updated API routes in `crates/api/src/routes/webhooks.rs` for soft-deletion and optional `include_deleted` query filtering. - Updated `crates/store/tests/store_tests.rs` migration version check to 21 and added test suite: `delete_webhook_soft_deletes_rather_than_hard_deleting`, `dispatch_skips_a_soft_deleted_endpoint`, `list_webhooks_excludes_soft_deleted_endpoints_by_default`, and `historical_deliveries_for_a_soft_deleted_endpoint_remain_queryable`. Closes Octo-Protocol-org#338 Co-authored-by: ���feyisaralawal <����feyisaralawal01@gmail.com> Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…ocol-org#333, Octo-Protocol-org#332, Octo-Protocol-org#335, Octo-Protocol-org#331) (Octo-Protocol-org#394) Detailed explanation of changes across all four resolved issues: 1. Propagate per-request id through logging for cross-service traceability (Closes Octo-Protocol-org#333): - Audited request handling across crates/api and implemented `request_id_middleware` in crates/api/src/lib.rs. - For every incoming HTTP request, extracts the caller-supplied `X-Request-Id` header (if valid ASCII and non-empty) or generates a new UUIDv4. - Enters an instrumented tracing span `info_span!("request", request_id = %request_id)` wrapping downstream route handling, store calls, Horizon requests, and webhook dispatch so all log lines carry the correlation id automatically. - Attaches `x-request-id` to response headers so clients can reference request IDs when reporting issues. - Added `tracing-subscriber` dev-dependency and comprehensive tests in `crates/api/tests/request_id_tests.rs`: * `every_response_carries_an_x_request_id_header` * `a_caller_supplied_x_request_id_is_echoed_back_unchanged` * `log_output_for_a_request_consistently_carries_the_same_request_id_across_nested_spans` 2. Consolidate is_safe_url into comprehensive edge-case test suite (Closes Octo-Protocol-org#332): - Hardened `is_safe_url` in crates/webhooks/src/lib.rs against SSRF vectors across all IP encoding classes: * Dotted-decimal IPv4, loopback range (127.0.0.0/8), private (RFC 1918), carrier-grade NAT (100.64.0.0/10), link-local (169.254.0.0/16), broadcast (255.255.255.255), and unspecified (0.0.0.0/8). * Alternative representations including raw decimal integer (`2130706433`), hex integer (`0x7f000001`), hex-dotted (`0x7f.0.0.1`), and octal-dotted (`0177.0.0.1`). * IPv6 loopback (`::1`), unspecified (`::`), link-local (`fe80::/10`), unique-local (`fc00::/7`), IPv4-mapped IPv6 (`::ffff:x`), and IPv4-compatible IPv6 (`::x`). - Documented explicit DNS scope boundary: `is_safe_url` handles syntactic validation and IP literal filtering, while DNS resolution and DNS rebind defense are delegated to the HTTP client and egress network policies. - Organized tests into structured test modules by encoding class: * `test_standard_public_urls` * `test_ipv4_literal_forms` * `test_ipv6_forms` * `test_ipv4_mapped_and_compatible_ipv6_forms` * `test_link_local_addresses` * `test_unspecified_addresses` * `test_hostnames_and_dns_scope_boundary` * `test_invalid_and_malformed_urls` 3. Add migration-order regression test on fresh database (Closes Octo-Protocol-org#335): - Added `migrate_applies_cleanly_from_a_genuinely_empty_database` in crates/store/tests/store_tests.rs. - Dynamically provisions a fresh, isolated PostgreSQL database from the base instance rather than reusing an existing or pre-migrated schema. - Runs `Store::connect` and `Store::migrate` (`MIGRATOR.run`) to verify all 20 sequential migrations apply cleanly in order from scratch. - Asserts key database tables exist (`wallets`, `addresses`, `transactions`, `withdrawals`, `webhook_endpoints`, `webhook_deliveries`, `_sqlx_migrations`) and drops the temporary test database upon completion. 4. Add cargo-audit and cargo-deny result caching to speed up CI (Closes Octo-Protocol-org#331): - Updated `.github/workflows/ci.yml` for both `audit` and `deny` jobs. - Added `actions/cache@v4` steps caching tool binaries (`~/.cargo/bin/cargo-audit`) and advisory databases (`~/.cargo/advisory-db` for cargo-audit, `~/.cargo/advisory-dbs` for cargo-deny). - Configured daily rotating cache keys (`${{ runner.os }}-cargo-audit-${{ steps.cache-date.outputs.date }}` and `${{ runner.os }}-cargo-deny-${{ steps.cache-date.outputs.date }}`) with prefix restore keys to prevent cache drift and ensure advisory freshness. - Preserved active advisory fetching so incremental fetches occur fast against warm caches rather than downloading full databases from scratch on every CI run. Co-authored-by: ���feyisaralawal <����feyisaralawal01@gmail.com> Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…to-Protocol-org#344, and Octo-Protocol-org#347 (Octo-Protocol-org#395) Resolves 4 issues simultaneously across test coverage, operational documentation, and observability: 1. Issue Octo-Protocol-org#340: Statistical smoke test for OTP code distribution - Verified that crates/email/src/lib.rs uses rand::rngs::OsRng (OS CSPRNG) to generate OTPs. - Added generate_otp_produces_a_roughly_uniform_distribution_of_digits_across_a_large_sample testing 100,000 generated OTP codes across all 6 digit positions to assert no systematic digit bias or modulo distortions. - Added generate_otp_duplicate_rate_across_a_large_sample_is_consistent_with_true_uniform_randomness testing duplicate collisions across 100,000 draws from the 1,000,000 code space against the birthday paradox expectation (~95,163 expected unique codes). - Documented that these tests serve as gross implementation bug smoke tests rather than full cryptographic certifications. - Closes Octo-Protocol-org#340 2. Issue Octo-Protocol-org#343: Proptest fuzz corpus for operation_index_from_toid - Added property-based fuzz tests using proptest! in crates/ingest/src/lib.rs. - Added operation_index_from_toid_never_panics_on_arbitrary_input fuzzing with arbitrary string inputs to guarantee crash freedom. - Added operation_index_from_toid_extracted_value_is_always_within_the_documented_valid_range_when_some across valid TOID patterns, whitespaced inputs, and boundary numbers asserting that any extracted operation index is non-negative and <= i32::MAX. - Closes Octo-Protocol-org#343 3. Issue Octo-Protocol-org#344: Operational runbooks for migrate-keys and backfill-operation-index - Created docs/runbook-migrate-keys.md providing end-to-end guidance for the dual-key rotation window, pre-flight checks, invocation examples (full rotation and cipher upgrade), healthy log indicators, store method references (Store::list_wallets_needing_reseal, Store::reseal_wallet), and interruption recovery/rollback procedures. - Created docs/runbook-backfill-operation-index.md providing guidance for historical deposit TOID operation index backfills, pre-flight candidate estimation, dry-run and live invocations, expected logs, store/ingest code cross-references (octo_ingest::operation_index_from_toid), and transactional idempotency guarantees. - Linked both runbooks in README.md under the Documentation section. - Closes Octo-Protocol-org#344 4. Issue Octo-Protocol-org#347: Named tracing spans around Horizon calls - Added distinct #[tracing::instrument] spans around public Horizon interaction methods in crates/api/src/horizon.rs (balances, account_sequence, account_info, submit_transaction, friendbot_fund) and crates/ingest/src/horizon.rs (payments_after). - Configured spans to record call metadata (call_type, account, cursor, limit) and dynamic outcome (success, circuit_open, not_found, rejected/tx_failed, failure) while skipping sensitive payloads (such as raw transaction XDR envelopes). - Added unit tests in crates/api/src/horizon.rs and crates/ingest/src/horizon.rs verifying named span emissions using custom test tracing subscriber layers. - Added tracing-subscriber to dev-dependencies for octo-api and octo-ingest. - Closes Octo-Protocol-org#347 Co-authored-by: ���feyisaralawal <����feyisaralawal01@gmail.com> Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
… under a constraint-violating write (Octo-Protocol-org#396) Closes Octo-Protocol-org#362 Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
…id_account in CI (Octo-Protocol-org#397) Adds a permanent, CI-run proptest corpus cross-validating is_valid_account's verdict against stellar-base's own strkey decoder across a wide randomized input space, following the same cross-validation methodology already established for asset-code validation. Two property tests are added to crates/wallet-core/src/address.rs: - is_valid_account_verdict_never_disagrees_with_stellar_bases_own_strkey_decode_across_a_wide_randomized_corpus Generates up to 80-char strings from the full Unicode char space (4096 cases) and asserts is_valid_account always agrees with PublicKey::from_string on each input. - boundary_biased_ascii_lengths_for_is_valid_account_never_disagree Biases toward lengths 50..=62 around the 56-char G... strkey boundary, catching any off-by-one in length gating. Both run as part of the default `cargo test` invocation with no manual flag, so they are always exercised in CI. Closes Octo-Protocol-org#361
…allet/import_wallet (Octo-Protocol-org#398) provision_wallet/import_wallet lacked a known-answer test vector proving a specific mnemonic derives a specific, independently-verifiable account, unlike the rigor already applied to raw derivation in derive.rs. Adds a cited test vector and round-trip tests. Two required tests are added to crates/wallet-core/src/provision.rs: - import_wallet_derives_the_expected_account_for_a_known_sep0005_test_vector Uses the published SEP-0005 Test 1 vector (no passphrase, 12-word mnemonic) from https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md. The same vector is independently verified by js-stellar-base, go/txnbuild, and the Python stellar-sdk, plus derive.rs's own sep0005_account_0_matches_official_vector. Asserts import_wallet derives exactly GDRXE2BQUC3AZNPVFSCEZ76NJ3WWL25FYFK6RGZGIEKWE4SOOHSUJUJ6. - provision_wallet_returns_a_mnemonic_and_account_that_are_mutually_consistent_via_import_wallet Calls provision_wallet, then re-imports its mnemonic via import_wallet and asserts the account matches — proving the two functions are mutual inverses end-to-end. The two pre-existing tests are preserved and renamed for clarity: - provision_then_reopen_seed_yields_same_account → sealed_seed_opens_and_re_derives_same_account - import_reproduces_account_from_mnemonic → superseded by the explicit vector test above Closes Octo-Protocol-org#360
…etError variants (Octo-Protocol-org#401) Closes Octo-Protocol-org#364 Co-authored-by: k2ghostyou <k2ghostyou@users.noreply.github.com> Co-authored-by: Lateef Tosin <Emmyt24@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
docs: add CONTRIBUTING.md
Closes #363