SoW: Desk management / Accounts and transfers

Master: SoW: Desk management, steps 9 to 12.

Tracking: Linear project Desk management. The ticket worksheet lists every ticket with its paths, acceptance, and dependencies.

Objective. A customer funds a selected account, gets another account from Operations or by its own request, and moves cash between its accounts.

Uses: customers, membership, and the deposit and withdraw permissions from Customer account access. Self-trade prevention groups from Cross-account self-trade prevention.

Releases

Step Release Outcome Tickets Needs
9 W2 - Fund the selected existing account Funding instructions and withdrawal context identify the intended account. 3 A-4889
10 S1 - Approval and account restrictions One read returns approval, mapping-review, and restriction status for a customer's accounts. 1 A-4897
10 W5 - Open another account through AX Operations Operations opens an approved account through a request that can be retried. 7 W2, S1, A-4890, A-4897
11 W6 - Create an account through customer self-service An authorized customer user requests an account on the W5 path. 4 W5, A-4892
12 Cash holds Orders, withdrawals, and transfers reserve source cash through one hold record. 3 A-4890
12 W10 - Transfer capital through AX Operations Operations executes one durable internal cash transfer. 7 Cash holds, A-4897
12 W11 - Transfer capital through customer self-service An authorized customer user submits the same transfer. 2 W10, A-4892
flowchart LR
  W2["9 · W2 funding instructions"] --> W5["10 · W5 Operations opens account"]
  S1["10 · S1 status read"] --> W5
  W5 --> W6["11 · W6 customer requests account"]
  H["12 · cash holds"] --> W10["12 · W10 Operations transfer"]
  W10 --> W11["12 · W11 customer transfer"]

Ticket W5.5 is delivered by Cross-account self-trade prevention.

Boundaries

Current behavior

Capability Source Consequence
Operations creates named accounts with an owner and venue identity. Account routes W5 adds the request key, recovery, and readiness.
Positions, P&L, equity, and margin are per account. Risk state W5.6 verifies two accounts with one owner. It adds no risk model.
Order admission checks the approval and freeze state of the account's customer. Order admission W5.4 reuses the customer checks.
USD instructions use the logged-in user's reference. USDC instructions use the selected account. Deposit screen, whoami W2 makes the USD reference identify the account.
Production withdrawals require an Architect representative. Withdrawal screen W2 keeps the manual process and names the account.
Every money event posts to one account against an AX system ledger. No account-to-account transfer exists. Funding checks, transaction kinds Step 12 adds the transfer.

These rows come from the source. Production customer configuration and the bank-matching procedure are verified under decision D2.

Decision records

The owner records each result in the master SoW decision record.

ID Owner Required output Gates
D2 Operations and Compliance Confirm the owner and account mapping, approval reuse, and the explicit-account manual withdrawal procedure. Review existing borrowing and unresolved ownership. The funding-screening identity and the bank reference are keyed by the customer id under decision 10 of the access SoW and need no separate confirmation. W2, W5, W10
D3 Risk, Legal, and venue Operations For each approved multi-account setup, record position aggregation, self-trade scope, outflow rule applicability, and shortfall coverage as verified existing, not required, or unresolved. Name the evidence. A second account for that customer. An unresolved item blocks activation of that setup.
D4 Operations and Compliance Approve creation mandates, customer-editable inputs, initial grants, account limits if required, the requests that Operations reviews, and the treatment of a pending request after authority or approval changes. W6
D5 Risk and Operations Approve cash eligibility evidence, directional user, source, and destination mandates, any additional source Withdraw requirement, destination restrictions, the authoritative paired-posting store, the hold protocol, and recovery of an uncertain operation. Cash holds, W10, W11. Unknown encumbrance is a rejection.

Transfer posting design

A transfer is one event with two legs: -amount on the source account and +amount on the destination account. The legs share an event_id.

Ticket plans

S1 — Approval and account restrictions · 1 ticket · Step 10

Shared prerequisite - Approval and account restrictions

Ticket Bounded change Reviewer Added + deleted lines Depends on
S1 Return approval, mapping-review, and account-restriction status B 180-340 A-4897

S1 - Return approval, mapping-review, and account-restriction status

Linear: A-4916

Change: Return the current approval reference, account restrictions, and mapping-review status for registered customer accounts. Reuse existing onboarding evidence. Do not create a second application or an access-management surface.

Acceptance: Cover approved, frozen, missing-owner, and conflicting-owner states. Reads do not change approval or suppress restrictions. Account creation consumes this status contract.

Depends on: A-4897

W2 — Fund the selected existing account · 3 tickets · Step 9

W2 - Fund the selected existing account

Deployable outcome: A customer receives clear funding instructions for the selected book and identifies that book when requesting a withdrawal.

Release acceptance: Use two Operations-created accounts. Switch between their USD and USDC instructions, fund the intended book through approved rails, request a withdrawal with an explicit account reference, and reconcile the result to that account.

Operating boundary: Works on existing accounts. USD withdrawals remain Operations-assisted. This release does not automate bank withdrawals or add internal transfers.

Whole-release prerequisites: None

Shared implementation prerequisites: Existing account creation and Treasury tools, plus A-4889 explicit funding permissions. The full Team release is not required.

Activation gates: D2; D3

Ticket Bounded change Reviewer Added + deleted lines Depends on
W2.1 Return funding instructions for the selected account B 240-460 A-4889
W2.2 Show the selected book in deposit and withdrawal instructions F 180-360 W2.1; A-4889
W2.3 Verify funding attribution on two existing books B 180-380 W2.1

W2.1 - Return funding instructions for the selected account

Paths: rs/api-gateway/src/auth_routes.rs; rs/api-gateway/src/admin_routes.rs; rs/sdk-internal/src/protocol.rs; rs/treasury-engine/

Change: Return account-scoped USD instructions that identify the intended book under the approved bank-matching procedure. Reuse account ACLs and USDC address lookup. Verify the explicit account target in Operations deposit and withdrawal tools and the correct owner used for screening. Preserve current funding restrictions. Require Deposit for instructions. Use the reviewed customer/evidence mapping for screening; the login is the actor, not the legal owner.

Contract: The displayed reference and Operations procedure identify the selected book. A user-derived reference alone cannot distinguish two books. An unsupported attribution path returns an actionable pending state.

Acceptance: Two books under one owner have unambiguous instructions. Test a delegate, an unrelated account, missing address or owner, restricted funds, and failed screening. Do not fall back to the login's default account. Use existing account IDs and manual matching first; a new reference schema needs a separate H ticket if the approved procedure requires it.

Depends on: A-4889

Split boundary: Split instruction/authorization APIs from demonstrated Treasury attribution repairs.

W2.2 - Show the selected book in deposit and withdrawal instructions

Paths: gui/packages/app/screens/portfolio/components/Transfer/; gui/packages/app/data/

Change: Pass the selected account to USD instructions as already done for USDC. Show account name and reference in the manual withdrawal instructions. Handle switching, loading, and missing instructions without showing the previous account's details.

Contract: Customers can identify which book receives or supplies funds. The production withdrawal screen continues to direct the customer to Operations.

Acceptance: Switch MM to prop while an instruction request is pending. Show only the selected account's response. Copy the correct funding reference. The withdrawal request identifies the selected book. Permission denial and unavailable instructions are clear.

Depends on: W2.1; A-4889

Split boundary: Split deposit instruction updates from the manual withdrawal account context.

W2.3 - Verify funding attribution on two existing books

Paths: rs/api-gateway/tests/sections/; rs/treasury-engine/tests/; rs/recon-engine/

Change: Add focused regression evidence for explicit account funding and screening. Repair only demonstrated defects. Pair the automated cases with an Operations check of the actual USD matching and withdrawal procedure at release acceptance.

Contract: A deposit, withdrawal, or replay changes only the intended account. Sandbox success alone does not establish that the production bank procedure works.

Acceptance: Test explicit non-default accounts, duplicate deposit events, missing attribution, pending screening, account restrictions, and restart. Reconcile each account's balance and transaction history. Record the Operations funding check under D2.

Depends on: W2.1

Split boundary: Split deposit replay tests from withdrawal attribution tests.

W5 — Open another account through AX Operations · 7 tickets · Step 9

W5 - Open another account through AX Operations

Deployable outcome: Operations opens an approved additional account that the customer can fund, select, trade, and withdraw from.

Release acceptance: Open Axtior's prop book under its confirmed owner. Grant its existing operator access. Fund, trade, close, and withdraw on the intended book. Verify separate accounting, required controls, and recovery without another company application.

Operating boundary: Operations performs creation using existing tools and recoverable provisioning. No customer creation form, new lending allocation, or shared margin is required. Existing borrowing must be reviewed.

Whole-release prerequisites: W2

Shared implementation prerequisites: A-4890 and S1 registration and status contracts only. The Team screen is not a prerequisite.

Activation gates: D2; D3

Ticket Bounded change Reviewer Added + deleted lines Depends on
W5.1 Store admin provisioning identity and readiness H 120-240 A-4890
W5.2 Persist and replay Operations desk-creation requests B 200-360 W5.1
W5.3 Resume venue provisioning and register the new desk B 240-440 W5.2; A-4897
W5.4 Reuse company approval and propagate restrictions to new desks B 240-460 W5.3; S1
W5.5 Verify the required self-trade prevention scope B 240-460 W5.3; W5.1
W5.6 Verify separate-book accounting and enable trading readiness B 260-480 W5.4; W5.5; W2.3
W5.7 Show Operations provisioning and customer desk readiness F 220-420 W5.2; W5.6

W5.1 - Store admin provisioning identity and readiness

Paths: db/postgres/1.sql

Change: Persist an Operations request key, one allocated account ID, immutable owner and desk inputs, venue progress, and readiness state. Store only the additional mandate or prevention-scope fields required by the approved venue contract.

Contract: Store one Operations provisioning request and account identity with pending readiness. The W6 customer mandate is a separate extension.

Acceptance: Validate uniqueness, immutable request identity, and legal-entity references. Represent unknown venue outcomes without allocating another account. A pending account is not trading-ready.

Depends on: A-4890

Split boundary: Split request identity from additional venue-policy fields if needed.

W5.2 - Persist and replay Operations desk-creation requests

Paths: rs/sdk-internal/db/src/entities.rs; rs/api-gateway/src/account_creation.rs; rs/api-gateway/tests/sections/

Change: Implement insert-or-read, immutable input checks, status transitions, and the admin submit/status contract for one desk-creation request. Allocate the account ID once. Reuse current exchange-admin authorization.

Contract: Provisioning receives a stable request and account identity. No customer-facing creation endpoint is introduced.

Acceptance: Concurrent admin retries return one account ID. Changed inputs fail. Restart retains progress. Customer callers cannot create requests or alter readiness.

Depends on: W5.1

Split boundary: Split request persistence from admin route adapters.

W5.3 - Resume venue provisioning and register the new desk

Paths: rs/api-gateway/src/account_creation.rs; rs/api-gateway/src/admin_trading_account_routes.rs; rs/ep3/; rs/api-gateway/tests/sections/

Change: Use the saved account ID in existing AX/EP3 provisioning. Recover uncertain remote outcomes. Set reviewed owner, fees, initial grants, and confirmed affiliation. Keep the account pending until W5.6 checks the required controls and funding readiness.

Contract: Create one recoverable account. Establish its approved control membership before activation. This does not require new group-control code when D3 records verified existing coverage.

Acceptance: Inject failure before venue creation, after remote success, and before local completion. Retry finds the same venue account and grants. No pending account becomes tradable. AIEX provisioning remains outside this AX release.

Depends on: W5.2; A-4897

Split boundary: Split stable-identity venue adaptation from local finalization and recovery.

W5.4 - Reuse company approval and propagate restrictions to new desks

Paths: rs/onboarding-gateway/; rs/api-gateway/; rs/order-gateway/; rs/sdk-internal/web-auth/

Change: Verify company-evidence reuse and required person checks on the new account. Preserve the existing owner approval/freeze checks and repair demonstrated activation, order, or funding defects. Keep the current evidence store.

Contract: The additional account uses approved owner and person status on enabled paths. Copying an owner field alone is insufficient acceptance evidence.

Acceptance: Use one approved company and multiple named traders. Test missing ownership, pending person checks, changed approval, entity freeze, stale replicas, disconnect, and reconnect. Define the maximum effective restriction delay. No duplicate company application is required merely to open another book.

Depends on: W5.3; S1

Split boundary: Split activation and owner-status handling from demonstrated active-session propagation repairs.

W5.5 - Verify the required self-trade prevention scope

Paths: rs/ep3/; rs/order-gateway/; rs/sdk-internal/test-batteries/

Change: Confirm the existing EP3 prevention mechanism and configured scope against the approved two-book setup. Keep passing behavior. Repair demonstrated account-scope or order-path gaps, including replace. Record venue evidence before activation.

Contract: Do not infer cross-account prevention from an order instruction alone. If a repair needs venue configuration or public SDK changes, estimate a separate H ticket before implementation.

Acceptance: Test same user/different accounts, different users/same account, and different users/related accounts under the approved rule. Verify an unrelated counterparty can trade. Repeat after reconnect and replace. Cross-account self-trade prevention delivers this ticket.

Depends on: W5.3; W5.1

Split boundary: Split venue scope assignment from gateway integration and cross-desk tests.

W5.6 - Verify separate-book accounting and enable trading readiness

Paths: rs/api-gateway/; rs/risk-engine2/tests/; rs/order-gateway/tests/; rs/recon-engine/

Change: Implement the final readiness check and focused two-book regression scenario. Reuse account selection, permissions, P&L, fees, funding, margin, and liquidation. Consume the approved D3 control assessment: each required rule must have verified existing coverage before activation.

Contract: New-account activation waits for applicable controls, not every proposed risk feature. Existing trading and accounting are verification work. Cash-funded launch cannot bypass existing loan restrictions.

Acceptance: Provision, fund, trade, close, and withdraw from the new book using one operator login. Check separate positions, balances, P&L, fees, margin, and account-scoped API keys. Test owner freeze, pending setup, crash, reconnect, and unrelated accounts. An unresolved required control blocks activation. Comparative reporting is not required. Prove resolved account_id through REST and WebSocket place/cancel/replace, venue identity, positions, open-order margin, event routing, and margin publication. Verify existing Operations-created second accounts too; no fallback to the actor's default account is permitted.

Depends on: W5.4; W5.5; W2.3

Split boundary: Split readiness enforcement from the focused accounting and trading recovery scenarios.

W5.7 - Show Operations provisioning and customer desk readiness

Paths: gui/apps/admin/; gui/packages/app/

Change: Extend the existing admin creation interface with confirmed owner/account scope, initial users, stable request key, and progress. Show the completed account in the existing customer selector and expose pending setup requirements to Operations.

Contract: Operations completes and recovers account creation. Customer self-service creation is delivered separately in W6.

Acceptance: Operations submits, refreshes, and recovers one request. Pending work never appears ready. The customer selects and trades the finished account with the existing login. No comparison dashboard or customer creation form is needed.

Depends on: W5.2; W5.6

Split boundary: Split the admin submission/progress view from the customer readiness display.

W6 — Create an account through customer self-service · 4 tickets · Step 11

W6 - Create an account through customer self-service

Deployable outcome: An authorized customer manager creates an additional account and assigns initial users without routine AX creation work.

Release acceptance: Axtior submits a prop-account request within its approved scope, refreshes after a timeout, recovers the same account, and sees readiness and rejection reasons. A customer cannot change legal owner or exchange-controlled terms.

Operating boundary: Reuse the complete W5 provisioning and readiness path. Creation authority is explicit and separate from trading or account-access management. Internal transfers and comparative reporting are not prerequisites.

Whole-release prerequisites: W5

Shared implementation prerequisites: A-4892 supplies the organization-removal contract. Its primitive can deploy before the Team screen.

Activation gates: D2; D3; D4

Ticket Bounded change Reviewer Added + deleted lines Depends on
W6.1 Store explicit customer account-creation mandates H 60-160 A-4890; W5.1
W6.2 Let Operations appoint and revoke account creators B 200-380 W6.1; A-4892
W6.3 Expose durable customer account creation and status B 240-460 W6.2; W5.6
W6.4 Add the customer account-creation form and progress view F 220-420 W6.3

W6.1 - Store explicit customer account-creation mandates

Paths: db/postgres/1.sql

Change: Add a creation mandate keyed by approved actor and scope with attribution and revocation state. Reuse confirmed affiliation and durable provisioning identity. Do not grant creation merely because accounts share an owner.

Contract: Absence of an active creation mandate denies customer creation. Ownership, management, and creation authority remain separate.

Acceptance: Validate scope references, uniqueness, and revoked mandates on a scratch database. Reject system-account scopes. Existing trading grants and owner links remain unchanged.

Depends on: A-4890; W5.1

Split boundary: Keep mandate DDL separate from persistence and execution adapters.

W6.2 - Let Operations appoint and revoke account creators

Paths: rs/sdk-internal/db/src/entities.rs; rs/api-gateway/; rs/admin-cli/; rs/api-gateway/tests/sections/

Change: Add bounded admin read, appoint, and revoke operations for creation mandates. Extend A-4892 organization removal to revoke applicable creation authority. Define the treatment of a revoked mandate while provisioning is pending.

Contract: Customer callers cannot appoint themselves. A new request needs current authority; pending work follows an explicit stop, review, or completion rule.

Acceptance: Test appointment, retry, revocation, unrelated scopes, and organization removal. Race revocation with submit and pending provisioning. Preserve authorized Operations recovery of an existing request.

Depends on: W6.1; A-4892

Split boundary: Split mandate persistence/admin API from the CLI and removal integration.

W6.3 - Expose durable customer account creation and status

Paths: rs/api-gateway/src/account_creation.rs; rs/api-gateway/src/customer_account_routes.rs; rs/sdk-internal/src/protocol.rs; rs/api-gateway/tests/sections/

Change: Add customer submit/status and permitted-scope queries on the W5 path. Accept a stable caller request key, account name, and allowed initial users. Derive owner, venue settings, fee policy, and allowed grants from approved server rules.

Contract: Retry returns the same account. Changed request inputs under the same key fail. Pending accounts remain restricted until all W5 readiness checks pass.

Acceptance: Test duplicate and concurrent submission, timeout, restart, foreign scope, forbidden initial users, changed approval, and revoked authority. Status discloses only authorized requests. A customer cannot set owner, exchange fees, or risk exemptions.

Depends on: W6.2; W5.6

Split boundary: Split scoped submit/status authorization from provisioning adapter integration.

W6.4 - Add the customer account-creation form and progress view

Paths: gui/packages/app/screens/account/; gui/packages/app/data/

Change: Add Create account for authorized actors. Select an approved scope, enter a name, assign permitted initial users, and retain the request key across refresh or uncertain responses. Reuse the existing selector for a ready account.

Contract: This is the first customer creation interface. It uses W6.3 and does not duplicate Operations provisioning or expose exchange-only settings.

Acceptance: Create one account, refresh while pending, recover a lost response, and open the ready account. Show denial, failed setup, changed authority, and required Operations review. Double click does not create another book.

Depends on: W6.3

Split boundary: Split creation input controls from persistent status and recovery display.

Cash holds · 3 tickets · Step 12

Cash holds

Deployable outcome: Orders, withdrawals, and transfers reserve cash on the source account through one hold record.

Release acceptance: On existing accounts, race withdrawals and orders against available capacity and recover an uncertain debit without duplicate spending.

Operating boundary: A hold reserves cash on one account. It does not read the state of the customer's other accounts.

Whole-release prerequisites: None

Shared implementation prerequisites: A-4890 supplies the customer reference.

Activation gates: D5

Ticket Bounded change Reviewer Added + deleted lines Depends on
W8.1 Store shared cash-hold state H 160-300 A-4890
W8.4 Reserve source capacity B 400-750 W8.1
W8.5 Enforce cash holds on withdrawals and competing orders B 260-480 W8.4

W8.1 - Store shared cash-hold state

Paths: db/postgres/1.sql

Change: Store operation-keyed cash holds with durable state and effective-debit references. External withdrawals and internal transfers use the same hold identity. Reuse account references.

Contract: There is one relevant source-capacity budget, not separate withdrawal and transfer budgets. Holding cash does not reserve group position quantity.

Acceptance: Validate stable operation keys, valid accounts, and terminal states. Represent committed debits whose projections are incomplete.

Depends on: A-4890

Split boundary: Keep hold-state DDL in one ticket.

W8.4 - Reserve source capacity

Paths: rs/risk-engine2/src/; rs/sdk-internal/risk/src/; rs/sdk-internal/db/

Change: Implement operation-keyed cash holds and the reviewed hold-to-debit handoff. Compose current account capacity and existing loan restrictions.

Contract: Orders, withdrawals, and transfers use the same cash-hold contract. Resolve a hold only after confirmed failure or an effective debit.

Acceptance: Race same-account spending. Test duplicate requests, changed risk, stale data, lost responses, and restart. Capacity cannot be released before debit projection. Account and loan restrictions stay enforced.

Depends on: W8.1

Split boundary: Review hold transitions and fault tests together where needed. Split before 1000 lines.

W8.5 - Enforce cash holds on withdrawals and competing orders

Paths: rs/api-gateway/; rs/treasury-engine/; rs/recon-engine/; rs/order-gateway/; rs/sdk-internal/risk/src/

Change: Wire enabled external withdrawal paths to W8.4 and make order admission honor the same holds on cache and fallback reads. Preserve authorization, screening, account margin, and loan checks. Recover a hold after effective debit or confirmed failure. Expose uncertain operations to Operations.

Contract: An advisory loan snapshot alone is insufficient serialization.

Acceptance: Race withdrawals with orders and other withdrawals. Test screening failure, changed restrictions, crash before/after debit, delayed projection, and restart. No enabled admin, customer, Treasury, or order path bypasses source holds. Never release or reissue an uncertain debit.

Depends on: W8.4

Split boundary: Split order hold integration from withdrawal/Treasury recovery adapters. Keep each spending race with its integration.

W10 — Transfer capital through AX Operations · 7 tickets · Step 12

W10 - Transfer capital through AX Operations

Deployable outcome: Operations executes and inspects an approved internal cash transfer between existing accounts.

Release acceptance: Operations moves eligible cash, retries after a lost response, and sees one linked debit and credit. Race the operation with orders, withdrawals, and liquidation. Recover and reconcile the same operation.

Operating boundary: This release includes the full financial path before exposing an executable endpoint. Existing approved accounts can participate without W5 or W6 creation. Unknown or unsupported encumbrance blocks the cash-only route.

Whole-release prerequisites: None

Shared implementation prerequisites: A-4890 and A-4897 supply customer affiliation. Cash holds (W8.1, W8.4, W8.5) supply the hold and execution contracts.

Activation gates: D2; D3; D5

Ticket Bounded change Reviewer Added + deleted lines Depends on
W10.1 Persist transfer requests, holds, and pair mandates H 140-280 A-4890; W8.1
W10.2 Implement transfer request persistence and pair authorization B 230-420 W10.1; A-4897
W10.3 Post both transfer legs in one durable transaction B 230-440 W10.2
W10.4 Reserve source capacity for an internal transfer B 220-440 W10.2; W8.4
W10.5 Make orders and withdrawals honor transfer holds B 250-460 W10.4; W8.5
W10.6 Recover transfers and reconcile their projections B 260-460 W10.3; W10.4
W10.7 Expose the complete transfer to AX Operations B 200-380 W10.3; W10.5; W10.6

W10.1 - Persist transfer requests, holds, and pair mandates

Paths: db/postgres/1.sql

Change: Add stable transfer requests and paired posting identities, immutable account/amount inputs, progress, actor attribution, and explicit pair/actor mandates. Reuse the cash holds from W8.1. Do not create another source-capacity budget.

Contract: Stable transfer and posting IDs support one economic effect and resumable projection. Sharing an owner or management mandate cannot grant transfer authority.

Acceptance: Reject same-account pairs, invalid amounts, duplicate operation keys, and invalid references. States can represent committed money with incomplete projection. Schema does not grant transfer rights from matching owners.

Depends on: A-4890; W8.1

Split boundary: Split pair-mandate DDL from transfer-state DDL if the schema is larger than estimated.

W10.2 - Implement transfer request persistence and pair authorization

Paths: rs/sdk-internal/db/src/entities.rs; rs/api-gateway/src/internal_transfer.rs; rs/api-gateway/tests/sections/

Change: Add insert-or-read, immutable-input checks, transfer state transitions, and bounded AX pair/actor mandate administration. Admit approved same-entity cash transfers only. Recheck relevant authority and restrictions at the agreed execution boundary. Positive evidence must establish that the source funds are eligible and unencumbered.

Contract: A persisted request is not yet an executable endpoint. Unknown encumbrance or unresolved required policy blocks execution. A committed operation remains inspectable by authorized staff after mandate revocation. A source Withdraw bit alone never authorizes a destination. Require the approved directional user/source/destination mandate. D5 records any extra source funding-bit requirement.

Acceptance: Test duplicate and changed-input requests, forbidden pairs, revoked mandates before posting, changed affiliation, pending restrictions, and recovery. Reject unsupported borrowing and uncertain encumbrance. Destination rules distinguish inactive accounts from restricted accounts allowed to receive approved deficit funding.

Depends on: W10.1; A-4897

Split boundary: Split mandate administration from request/state persistence, with authorization tests in the former.

W10.3 - Post both transfer legs in one durable transaction

Paths: rs/transaction-engine/src/lib.rs; rs/transaction-engine/src/store.rs; rs/transaction-engine/src/functional_tests.rs; rs/api-gateway/src/internal_transfer.rs

Change: Reuse the transaction engine for an atomic linked debit and credit with stable identities. Persist authoritative committed transfer identity with the paired posting. Derive any separately stored workflow status from that result through an explicit recoverable protocol. Do not implement two independent deposit/withdraw calls.

Contract: Both monetary legs commit atomically. D5 must identify the authoritative commit store. If workflow status lives in another store, it recovers from the authoritative paired posting and cannot authorize a second effect.

Acceptance: Debit and credit equal amounts once. Concurrent duplicates have one effect. Failure before commit changes neither balance; a lost acknowledgement cannot post again. Test precision, source restrictions, and replay. Transfers affect account cash flows, not trading P&L; the paired amounts cancel in entity cash flow. Account history shows both sides.

Depends on: W10.2

Split boundary: Split paired-posting primitive from durable operation-state integration; keep atomicity tests with the integration.

W10.4 - Reserve source capacity for an internal transfer

Paths: rs/risk-engine2/src/; rs/sdk-internal/risk/src/; rs/sdk-internal/db/src/entities.rs; rs/api-gateway/src/internal_transfer.rs

Change: Adapt the W8.4 cash-hold protocol to an internal transfer. Compose current source capacity, account/loan restrictions, and destination eligibility. Use the same stable operation ID through reservation, posting, and projection.

Contract: Reuse shared cash-hold transitions. W10.5 proves all competing spending paths honor the integrated transfer.

Acceptance: Race transfers for the same funds. Reject failed admission without a hold. Test restart, authority changes, stale risk, and hold-to-debit handoff. Verify a D5-approved transfer into a deficient account. Pending debit and projection cannot increase source capacity.

Depends on: W10.2; W8.4

Split boundary: Split transfer admission/policy composition from commit-projection integration. The shared reservation protocol is estimated in W8.4.

W10.5 - Make orders and withdrawals honor transfer holds

Paths: rs/order-gateway/src/state.rs; rs/sdk-internal/risk/src/; rs/api-gateway/src/utils.rs; rs/risk-engine2/src/; rs/order-gateway/tests/; rs/api-gateway/tests/sections/

Change: Integrate transfer operation kinds with the shared W8.5 order and withdrawal capacity checks. Verify cache and fallback reads, all enabled spending paths, and account restrictions. Do not implement independent spending budgets.

Contract: Orders, external withdrawals, and internal transfers honor the same relevant source holds. Operations access cannot bypass this requirement.

Acceptance: Deterministically race a transfer against an order and against a withdrawal. Combined admitted spending stays within capacity. Exercise restart, stale cache, and hold-to-debit handoff. Fail closed if a spending path cannot establish current capacity.

Depends on: W10.4; W8.5

Split boundary: Split order admission integration from withdrawal integration. Keep the corresponding race test with each.

W10.6 - Recover transfers and reconcile their projections

Paths: rs/api-gateway/src/internal_transfer.rs; rs/recon-engine/src/checks/; rs/risk-engine2/src/tigerbeetle_driver.rs; rs/transaction-engine/src/faulty_store.rs

Change: Resume incomplete transfers after restart and finish balance/risk/history projection with stable IDs. Release a hold only after the debit is effective or failure is confirmed. Reconcile unmatched legs and expose old pending operations with an assigned Operations recovery procedure.

Contract: Pending and committed results remain inspectable; reconciliation reports inconsistency and recovery resumes existing work.

Acceptance: Inject failure after reservation, paired commit, projection, and before acknowledgement. Recovery cannot issue another credit or release capacity early. Reconcile both account histories and cash-flow rows. Race liquidation and transfers. Alert or query old pending operations; an operator resumes the original operation.

Depends on: W10.3; W10.4

Split boundary: Split runtime recovery/projection from the reconciliation adapter, with fault tests in recovery.

W10.7 - Expose the complete transfer to AX Operations

Paths: rs/api-gateway/src/admin_trading_account_routes.rs; rs/api-gateway/src/internal_transfer.rs; rs/admin-cli/src/accounts.rs; rs/api-gateway/tests/sections/

Change: Wire one admin submit/status operation and a CLI command to the completed persistence, authorization, reservation, posting, and recovery path. Return operation reference and pending/completed result.

Contract: This is the first executable internal-transfer interface. It completes an Operations release using approved existing accounts. Customer submission and the transfer form are W11.

Acceptance: Operations completes and inspects one approved cash transfer through CLI/API. Retry uses the same operation. Reject forbidden pairs, encumbered cash, unresolved policy, and unauthorized actors. Race order, withdrawal, transfer, and liquidation. Account readiness can be established through existing Operations review; W5 provisioning is not mandatory.

Depends on: W10.3; W10.5; W10.6

Split boundary: Split the CLI adapter from the admin submit/status endpoint, preserving full execution checks in the endpoint.

W11 — Transfer capital through customer self-service · 2 tickets · Step 12

W11 - Transfer capital through customer self-service

Deployable outcome: An authorized customer selects an approved account pair, transfers eligible cash, and recovers the operation status without routine AX action.

Release acceptance: Axtior completes one permitted transfer from the customer screen. Retry, refresh, and a lost response return the same result. A trader without transfer authority cannot submit.

Operating boundary: Reuse W10 execution and financial checks. Do not duplicate the ledger or reserve funds in the GUI. Account creation and comparative reporting are not prerequisites.

Whole-release prerequisites: W10

Shared implementation prerequisites: A-4892 supplies organization removal. W11.1 must revoke applicable transfer mandates through the same contract.

Activation gates: D2; D3; D5

Ticket Bounded change Reviewer Added + deleted lines Depends on
W11.1 Expose the completed transfer to an authorized customer B 180-340 W10.7; A-4892
W11.2 Add the customer internal-transfer form F 240-440 W11.1

W11.1 - Expose the completed transfer to an authorized customer

Paths: rs/api-gateway/src/customer_account_routes.rs; rs/api-gateway/src/internal_transfer.rs; rs/sdk-internal/src/protocol.rs; rs/api-gateway/tests/sections/

Change: Add customer submit/status and permitted-pair reads to the complete W10 transfer service. Require confirmed scope and explicit transfer authority. Extend organization removal to revoke applicable transfer mandates. Reuse cash eligibility and current restrictions.

Contract: Return permitted pairs, currency, stable operation ID, status, and safe rejection reason. Management authority alone is insufficient. The Team screen is not required to use the transfer API. The directional mandate remains mandatory even when the user has source Withdraw. D5 must settle whether that bit is also required; deny unsupported policy combinations.

Acceptance: Deny traders or managers without a mandate, foreign account IDs, and cross-customer pairs. Retry and reconnect return the same operation. Pair/status reads expose no unrelated values. Organization removal prevents new transfers while authorized Operations can recover committed work.

Depends on: W10.7; A-4892

Split boundary: Split permitted-pair/status reads from submission; keep mandate checks on both.

W11.2 - Add the customer internal-transfer form

Paths: gui/packages/app/screens/portfolio/components/Transfer/; gui/packages/app/data/

Change: Add between-account transfer selection, amount, confirmation, and operation status to the existing funds panel. Reuse transaction history and persist the submitted request key across uncertain responses.

Contract: Uses W11.1 for customer transfer submission and status. Reuse existing account history. No currency conversion, automatic rebalancing, new ledger, or comparative reporting dependency.

Acceptance: Customer completes one permitted transfer and sees the linked result. Double click, timeout, and reconnect do not submit a new operation. Pending and rejected outcomes are clear. Changed authority refreshes available actions.

Depends on: W11.1

Split boundary: Split transfer form from persistent status/history integration; both remain frontend-only.

Engineering reference

Ticket rules

Each ticket maps to one CODEOWNERS team. H owns db/ and other protected paths, B owns the listed Rust paths, and F owns gui/. Schema work goes in db/postgres/1.sql. A required public SDK or venue configuration change gets a separately estimated H ticket.

Split tickets by reviewable contract. Most estimates are below 500 changed lines, including tests. W8.4 is the exception (400-750). Split before 1000 lines. Fault tests stay in the ticket that adds the behavior.

Release acceptance invariants

Property Required evidence
Legal affiliation is independent of access authority. Grant edits, manager replacement, and member removal do not change ownership.
Each account keeps its accounting and margin result. Positions, P&L, fees, funding, and margin reconcile per account. Reports and pending credits grant no buying power.
Each provisioning request creates at most one account. Stable request identity survives timeout, remote success without acknowledgement, restart, and changed-input retry. A pending account cannot trade.
A logical transfer produces at most one paired economic effect. Duplicate requests, concurrent workers, crash, replay, and delayed projections do not duplicate postings or release source capacity early.
All enabled spending paths honor the same cash holds. Deterministic races between orders, withdrawals, and transfers, including cache and fallback reads and active loan restrictions.

For stateful tickets, enumerate operation phase, authority state, and failure mode. Each relevant case needs a deterministic test or a construction argument. Include client disconnect, server disconnect, restart, and reconnect.