@venlyfinance/settlement-mcp 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/frontend.d.ts +6 -5
- package/dist/frontend.js +200 -53
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.0 – 2026-08-22
|
|
4
|
+
|
|
5
|
+
- The runtime `@venlyfinance/sdk` dependency moves to `^0.7.0`, so the server's own
|
|
6
|
+
data plane matches the world its blueprints describe (0.7.1 and earlier installed a
|
|
7
|
+
0.5.x sdk at runtime).
|
|
8
|
+
- The `send` journey blueprint is rewritten for the one-door send surface: recipient-object
|
|
9
|
+
fork (platform directory · saved payout recipients · own bank account), step-up
|
|
10
|
+
confirmation on every money confirm, and the forbidden-to-invent list (fee row, "No fee"
|
|
11
|
+
claim, ETA, pre-create rate, named stages beyond the status enum, any external-wallet
|
|
12
|
+
surface).
|
|
13
|
+
- New `console-webhooks` journey blueprint; the operator-console blueprints
|
|
14
|
+
(`console-review-queue`, `console-decision-detail`, `console-pricing-config`,
|
|
15
|
+
`console-simulator`) now name their shipped registry blocks instead of empty arrays.
|
|
16
|
+
|
|
17
|
+
## 0.7.1 – 2026-08-21
|
|
18
|
+
|
|
19
|
+
- Republish so the packaged blueprints carry the corrected npm ranges for
|
|
20
|
+
`@venlyfinance/react` (`^0.5.0`) and `@venlyfinance/sdk` (`^0.6.0`). The
|
|
21
|
+
0.7.0 tarball was cut before that fix landed, so its blueprints told agents
|
|
22
|
+
to install ranges that never reach the versions the registry blocks import.
|
|
23
|
+
No behaviour change beyond the stamped ranges.
|
|
24
|
+
|
|
3
25
|
## 0.7.0 – 2026-08-19
|
|
4
26
|
|
|
5
27
|
The MCP now pushes a machine-checkable runtime contract instead of relying on
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Shared constants. The default environment is MOCK so an unconfigured run
|
|
2
2
|
* never touches real infrastructure; staging/production are explicit. */
|
|
3
3
|
export declare const SERVER_NAME = "venly-finance-mcp-server";
|
|
4
|
-
export declare const SERVER_VERSION = "0.
|
|
4
|
+
export declare const SERVER_VERSION = "0.8.0";
|
|
5
5
|
export declare const INSTRUCTIONS = "Venly Finance build advisor. This server is a build-time advisor, not your app's data plane. The data plane is the published packages: every read is a hook and every regulated lifecycle a flow machine from `@venlyfinance/react`, inside `<VenlyProvider environment=\"mock\">` \u2013 zero credentials, zero network; server-side code uses `@venlyfinance/sdk`. Hand-rolled fetch layers, in-memory money stores, or route handlers that re-implement transfers, balances, or approvals are off-contract and fail review. UI installs from the @venlyfinance shadcn registry: `npx shadcn@latest add @venlyfinance/balances @venlyfinance/send \u2026` (auto-installs the npm packages). Before scaffolding, read `venly://frontend/agents` \u2013 it is the composition doctrine (AGENTS.md). Consult `get_journey_blueprint` per screen; gate finished screens with `review_screen` and `npx @venlyfinance/settlement-mcp review \"src/**/*.tsx\"`.";
|
|
6
6
|
export declare const ENVIRONMENT_FLAG = "VENLY_ENV";
|
|
7
7
|
export type VenlyEnvironment = "mock" | "qa" | "staging" | "production";
|
package/dist/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Shared constants. The default environment is MOCK so an unconfigured run
|
|
2
2
|
* never touches real infrastructure; staging/production are explicit. */
|
|
3
3
|
export const SERVER_NAME = "venly-finance-mcp-server";
|
|
4
|
-
export const SERVER_VERSION = "0.
|
|
4
|
+
export const SERVER_VERSION = "0.8.0";
|
|
5
5
|
export const INSTRUCTIONS = `Venly Finance build advisor. This server is a build-time advisor, not your app's data plane. The data plane is the published packages: every read is a hook and every regulated lifecycle a flow machine from \`@venlyfinance/react\`, inside \`<VenlyProvider environment="mock">\` – zero credentials, zero network; server-side code uses \`@venlyfinance/sdk\`. Hand-rolled fetch layers, in-memory money stores, or route handlers that re-implement transfers, balances, or approvals are off-contract and fail review. UI installs from the @venlyfinance shadcn registry: \`npx shadcn@latest add @venlyfinance/balances @venlyfinance/send …\` (auto-installs the npm packages). Before scaffolding, read \`venly://frontend/agents\` – it is the composition doctrine (AGENTS.md). Consult \`get_journey_blueprint\` per screen; gate finished screens with \`review_screen\` and \`npx @venlyfinance/settlement-mcp review "src/**/*.tsx"\`.`;
|
|
6
6
|
export const ENVIRONMENT_FLAG = "VENLY_ENV";
|
|
7
7
|
export function resolveVenlyEnvironment(env) {
|
package/dist/frontend.d.ts
CHANGED
|
@@ -14,17 +14,18 @@ declare const JOURNEYS: {
|
|
|
14
14
|
readonly team: "# Team\nShell: in-shell content column.\nRegistry items: venly-tokens, data-table, status-pill; block: team (TeamTable, InviteDialog).\nBinding: a TeamAdapter over your auth provider (createMockTeamAdapter for demos).\nStates that must exist: ACTIVE/INVITED/DISABLED members on first paint, invite\ncreated (display-only link in mock - never a fake sent-email claim), role\nchange persisting, self-actions blocked with the reason.\nRules that must hold: member status is word + glyph; role controls live in the\nrow; you cannot change your own role or disable yourself - the control is\ndisabled AND explains why.";
|
|
15
15
|
readonly "home-balances": "# Home / balances\nShell: left nav rail + thin top bar; full-width content.\nRegistry items: venly-tokens, balance-card, data-table, status-pill; block: balances (BalancesBlock, BalanceMiniature).\nHooks: useAccounts, useWallets; balances rendered per asset across the account's wallets.\nStates that must exist: loading, zero balances (first-run guidance), reserved buckets, entirely reserved (available 0 rendered honestly - the acct-escrow seed exercises it), balance load error degrading locally with a retry.\nRules that must hold: available is the emphasised figure and the only one above the rule; reserved is demoted by position and scale, never colour, and carries the still-yours qualifier; unspendable buckets carry the padlock; masking covers every figure including the chrome miniature; arithmetic mismatches are surfaced, never corrected; never assume stablecoin parity - render the quoted rate.";
|
|
16
16
|
readonly receive: "# Receive\nShell: content column - a warning callout, the field card, an advisory below.\nRegistry items: venly-tokens, field-list; block: receive.\nHooks: useVirtualBankAccounts (first active EUR account).\nStates that must exist: no virtual bank account yet (offer creation), details present, reference not yet assigned (\"Not assigned yet\" + Required pill - never \"(not required)\").\nRules that must hold: the payment reference is enforced as mandatory (amber Required pill, warning above the fields); per-field copy names the field it copied and only confirms on a successful write; rows never vanish - render the \"(not required)\" variant.";
|
|
17
|
-
readonly send: "# Send\nShell: full page;
|
|
17
|
+
readonly send: "# Send (one door)\nShell: full page; the door is the recipient picker; forms clamp ~600px; the\nreview and the step-up ceremony replace the form in place.\nRegistry items: venly-tokens, status-pill, field-list, data-table, list-error;\nblocks: send (SendDoor, RecipientPicker, DirectoryPick, PlatformTransferFlow,\nPayoutSendFlow, SendReview, StepUpConfirm, TransferDetail, PayoutDetail) and\nrecipients (RecipientsView, AddRecipientForm, BeneficiaryAccountForm,\nRouteCeremony) - the prerequisite surface saved recipients are managed on.\nHooks: useCreateFiatTransfer and useCreateCryptoTransfer (the staged-transfer\nmachine typed per rail), useRequestPayout, usePartyRoles, useAddPartyRole,\nuseCreateParty, useRegisterPayoutBankAccount, useCreatePayoutRoute,\nusePreparePayoutOwnershipProof, useCompletePayoutOwnershipProof, useParties,\nuseAccounts, useWallets, useAccountSupportedAssets, useTransfers, useTransfer,\nusePayouts, usePayout, usePayoutRoutes.\nBinding: ONE door - the first screen is the recipient picker and the fork is\nthe recipient's OBJECT TYPE, never a rail choice. A person or business on the\nplatform (a directory YOUR user table serves; render name + handle, never a\nUUID - ids stay request-side) starts an on-platform transfer. A saved\nrecipient - a party holding the payout-recipient role, owning reviewed bank\naccounts (details masked server-side) and an ACTIVE payout route - starts a\nthird-party payout referencing the ROUTE, never raw bank details. Your own\nbank account is a link row into the withdraw flow. Send-to-external-wallet\nhas NO surface: no teaser, no disabled row, no rendered trace.\nStates that must exist: recipient picker (three classes, populated and empty), disabled with the reason (unverified directory rows, non-active routes and non-active accounts), over-balance, review (known figures only), step-up (wrong code blocks, the deterministic demo code proceeds), pending, completed, failed (the record's own error verbatim, terminal), requested, sending, provider processing, rejected, returned (money came back - a neutral terminal), no active route (blocked start with the unblocking CTA), load failure (explicit error plus retry - never an empty detail).\nRules that must hold: every money confirm passes the step-up ceremony against\nYOUR auth adapter and the commit fires only after the code verifies - this is\napp-side ceremony and must never be presented as an API security guarantee;\nexecution is single-shot on an idempotency key minted ONCE per staged draft,\nso a retry replays the same record instead of moving money twice; reviews\nrender ONLY figures the API has produced, and the payout review states the\nabsence in words beside the two-sided units sentence. Forbidden to invent\n(render the labelled omission or nothing at all): a fee row - and equally a\n\"No fee\" claim, since no source confirms zero; an ETA or delivery date - no\ntiming field exists on transfers or payouts; a pre-create rate or\nrecipient-gets figure - exchangeRate and settledFiatAmount exist on CREATED\nand COMPLETED records only; named in-flight stages beyond the status enums -\nrender the app-side observation log instead. Beneficiary details come back\nmasked: render the mask, never re-ask. Route states render verbatim and a\nREJECTED route is terminal-negative with a way forward, never a dead end.";
|
|
18
18
|
readonly activity: "# Activity\nShell: full-width table + side panel.\nRegistry items: venly-tokens, data-table, status-pill, side-panel, timeline; block: activity.\nHooks: useTransfers (and useRampRequests where ramps are in scope).\nStates that must exist: loading, empty ledger, rows with pending/failed pills, open detail panel that stays in sync with refetches.\nRules that must hold: a row click opens the panel, never navigates; no scrim - the source row stays tinted; settled rows stay quiet (colour is a budget; pills only where action or failure lives); the panel's hero is the amount; the failure reason rides the terminal timeline node.";
|
|
19
19
|
readonly "onboarding-status": "# Onboarding / verification status\nShell: full page, form clamped ~600px; a status home once submitted.\nRegistry items: venly-tokens, timeline, status-pill, field-list; block: onboarding (CompanyForm, VerificationStatusHome, RestrictedBanner).\nHooks: useCreateParty, useCreateAccount, useParty, useAccount; verification status from the party/account records verbatim.\nStates that must exist: collecting (review before submit), submitted/waiting (say who acts next, on which channel, what still works meanwhile), approved, declined (humane copy, review-request as the primary action), re-verification on a live account (banner naming what pauses and what keeps working).\nRules that must hold: never render a fake progress percentage - use real status; a waiting state answers how long / who acts / what still works, and where no review window is published the copy says so instead of inventing one; a decline explains and offers a next step, not a dead end; creating a party is NOT completed verification - show the honest state.";
|
|
20
20
|
readonly "withdraw-bank-accounts": "# Withdraw + bank accounts (off-ramp)\nShell: settings page for the whitelist; full page for the flow, form clamped ~600px.\nRegistry items: venly-tokens, data-table, status-pill, timeline, field-list, arithmetic-ladder; blocks: bank-accounts (BankAccountsBlock, AddBankAccountForm), withdraw (WithdrawFlow, WithdrawalsTable, ConnectedWithdrawDetail).\nHooks: useCompanyBankAccounts, useBankAccountConfig, useCreateCompanyBankAccount, useRampRequests, useRampRequest, useCreateRampRequest, useFeeQuote, useRampPairs, useReferenceData, useFourEyesApproval, useInitiateRamp, describeRampStatus.\nStates that must exist: empty whitelist (one CTA), account in review / verified / declined, no-verified-destination block, amount over balance (two-place signal), fee quote with its unit, awaiting approval (creator sees why they can't approve), stale decision (409 - refetch and re-decide, never auto-retry), awaiting funds (deposit instructions + mandatory reference + tx-hash report), processing, paid out, failed, rejected, cancelled, on hold.\nRules that must hold: destinations are the company's OWN verified accounts - unverified rows are disabled with the reason, never hidden; the pre-create review renders only known figures (no invented rate, no bank-receives placeholder - the created record carries the fiat arithmetic and the detail opens on it); a refusal never reads as a wait; the event timeline renders actor, role and absolute timestamps.";
|
|
21
21
|
readonly reconciliation: "# Reconciliation\nShell: split pane (roughly one-third list, two-thirds evidence) - not a drawer.\nRegistry items: venly-tokens, data-table, side-panel, status-pill, field-list.\nHooks: reconcile_by_reference_code (MCP composite) or useVirtualBankAccounts + useTransfers joined on referenceCode.\nStates that must exist: matched, unmatched with candidate expectations, partial/many-to-one with a live shortfall figure, resolved.\nRules that must hold: show per-signal match rationale (which fields agree), never a bare score; keep zero-counts visible - an empty exception queue is information; keyboard row-stepping for review throughput.";
|
|
22
22
|
readonly "proof-of-segregation": "# Proof of segregation\nShell: content column, single card.\nRegistry items: venly-tokens, field-list, balance-card.\nHooks: useWallets, useAccount; on-chain balance beside the ledger figure.\nStates that must exist: reconciled (figures agree, timestamped), reconciling, source unavailable (say so - never render a stale figure as current).\nRules that must hold: the wallet address renders monospace with copy; the on-chain figure and ledger figure sit side by side with their as-of times; discrepancies are stated, not smoothed.";
|
|
23
23
|
readonly approvals: "# Approvals\nShell: full-width queue + side panel tailored to the approver.\nRegistry items: venly-tokens, data-table, status-pill, side-panel, timeline.\nHooks: useRampRequests, useFourEyesApproval (capability decides what renders), useRampLifecycle.\nStates that must exist: queue with awaiting-approval items, detail with the decision context beside the figures, applied, stale-version (someone acted first - refetch and re-decide), creator-view (cannot approve own request - render the rule, not a disabled mystery button).\nRules that must hold: the optimistic-locking version travels with every decision; a 409 means re-decide against fresh state, never auto-retry; reject requires a reason; the creator sees why they cannot approve.";
|
|
24
|
-
readonly "console-review-queue": "# Console review queue (the operator worklist)\nShell: left nav rail + thin top bar, full-width content, and a page-edge\nenvironment banner naming mock mode. Not a consumer surface - density rules\napply.\nRegistry items: venly-tokens, data-table, status-pill, money, list-error
|
|
25
|
-
readonly "console-decision-detail": "# Console decision detail (evidence, ceremony, audit trail)\nShell: side panel about 30% wide over the queue - no scrim, the table stays\nvisible clipped at the panel edge and the source row stays tinted. Escalate to a\n35/65 split only when the evidence outgrows the panel. Evidence goes on the\nLEFT: this is a judging task, not an authoring one.\nRegistry items: venly-tokens, side-panel, timeline, field-list, status-pill,\nmoney, data-table.\nHooks: useAccount, useParty, useWallets, useTransfers,\nuseVirtualBankAccounts, useVenlyMock (the trail reads the mock's event log).\nTwo timeline columns, not one feed: the decision chain (who decided what, when,\nin which seat) beside money movement on the same subject. Different actors,\ndifferent audiences; merging them is what makes an audit trail unreadable.\nStates that must exist: loading, evidence present, evidence unavailable, decision owed, decision applied, stale decision, terminal decision, frozen, empty trail.\nRules that must hold: every evidence row is either a real field path or a\nlabelled omission, and an omission is a FIRST-CLASS type in the component's\nprops, so a placeholder cannot be rendered where a gap belongs;\nomission copy states only what is verified and never implies a result, a\npending state, or a clean one - and never mentions the API contract, which is\ndeveloper diagnostics rather than operator language; a field the API cannot\ncarry is captured anyway when the work needs it, and rendered with a visible\nbadge saying it is a console note rather than API state; every decision carries the\noptimistic-locking version, and a conflict means refetch and re-decide against\nfresh state, never auto-retry; every transition the console causes leaves a\ntimeline node with actor, role and a timezone-qualified absolute timestamp, so a\nstatus change with no node is a bug; a store resync is a system line, not a\ndecision node; the panel footer carries row-stepping key chips so the reviewer\nmoves row to row without closing.";
|
|
26
|
-
readonly "console-pricing-config": "# Console pricing configuration\nShell: in-shell content column. A config screen, not a queue: no whose-move\nvalue and no aging.\nRegistry items: venly-tokens, data-table, arithmetic-ladder, field-list.\nHooks: useCompanyFees.\nBinding: the fee data the packages actually serve is a VOLUME-TIER model - tier\nname, ramp direction, minimum and maximum volume, percentage, version - and it\nis the same model the shipped withdrawal quote consumes, so this screen shows\nwhere a real quote comes from. A second, richer per-rail configuration model\nexists on an internal plane and is NOT served here; it renders as a labelled\nomission, never as an empty form.\nStates that must exist: loading, tiers present, no tiers, configuration unavailable, worked example, save failed.\nRules that must hold: a worked arithmetic ladder is mandatory on the tier\nsection - a sample amount times the tier percentage, with the operator glyphs in\na left gutter - because a pricing screen that shows only stored numbers teaches\nnothing; the ladder renders ONLY over data that exists, never over the omitted\nsection; the tier\na sample amount falls into is highlighted in the table so the row and the ladder\nare visibly the same fact; a single-member enum renders as a disabled\nsingle-value field that says so, not a select pretending at choice; a date\nwindow that has not opened reads scheduled, never active; forms are single\ncolumn with the field width capped, label above input, helper text between them\nand the error below.";
|
|
27
|
-
readonly "console-simulator": "# Sandbox simulator (play the counterparty)\nShell: its own chrome - a scrimmed right-hand drawer on a distinct surface with\na persistent sandbox label, reachable from ONE fixed affordance in the top bar.\nIt is the only scrimmed drawer in the console, so the surface change alone\nsignals the register change.\nRegistry items: venly-tokens, field-list, status-pill, money.\nHooks: useVenlyMock. Every control maps to exactly one call on the mock's\nsimulations namespace - no control without a call, and no call renamed.\nBinding: inbound credits, provider progression and screening verdicts are things\nOTHER parties do, so they live here rather than in the operator's workflow.\nStates that must exist: drawer closed, drawer open, sharing, not sharing, credit landed, verdict returned, payout advanced, books balanced, books do not balance, reset.\nRules that must hold: controls are phrased as events that happen to you, in the\nthird person, while operator controls elsewhere are imperative decisions - a\ncontrol phrased in the wrong voice is in the wrong surface; a simulated\ntransition emits the SAME event the real path emits, and the trail attributes it\nto the simulator plainly rather than to an operator; the drawer is reachable\nonly from the top bar, never from a queue row or a decision panel, because those\npaths make another party's action look like the operator's; the ledger check gets\na visible surface: it is the one control here that asserts something true, namely\nthat the simulated books balance; the channel footer states the adapter, session\nand peer count, and says IN WORDS when the surface is not actually sharing - the\ndefault channel shares nothing and cross-context sharing is same-origin only, so\nwithout that line a two-context demo can prove nothing while looking correct.";
|
|
24
|
+
readonly "console-review-queue": "# Console review queue (the operator worklist)\nShell: left nav rail + thin top bar, full-width content, and a page-edge\nenvironment banner naming mock mode. Not a consumer surface - density rules\napply.\nRegistry items: venly-tokens, data-table, status-pill, money, list-error;\nblocks: console-queue (ConsoleQueue, WhoseMove, AgeCell, deriveKycActor,\nderivePayoutActor - the derivation functions are exported so a consumer can\nunit-test the join).\nHooks: useAccounts, useParties. The queue's own state is DERIVED on every\nrender - never stored, never cached as a status.\nBinding: sections are ACTORS, not statuses - your move, waiting on the customer,\nwaiting on a provider, then a collapsed closed section, so the reviewer's own\nworklist is the top band by construction.\nStates that must exist: loading, your move, waiting on the customer, waiting on a provider, closed, empty queue, filtered to nothing, list error.\nRules that must hold: the whose-move value is a pure function of enum values on\nthe row - no clock reading, no threshold, no configuration and no default, and a\ncombination the mapping does not cover renders NO value plus an explicit\nnot-recognised line, which is a bug report rather than a guess; never a target\ntime, a breach colour or an overdue state, because the API publishes no targets\nand an invented one is the same defect as an invented fee; an age column is\nlabelled for what it actually measures - a created-at delta is \"Age\", and only a\nduration the API itself computes may be called time in state; empty sections are\nstill drawn as a zero header row, because nothing-to-do is information; loading\nis a skeleton that preserves column geometry exactly, never prose; a row click\nopens a side panel and never navigates; one status pill per row - the whose-move\nvalue is plain text, since two pills read as two states.";
|
|
25
|
+
readonly "console-decision-detail": "# Console decision detail (evidence, ceremony, audit trail)\nShell: side panel about 30% wide over the queue - no scrim, the table stays\nvisible clipped at the panel edge and the source row stays tinted. Escalate to a\n35/65 split only when the evidence outgrows the panel. Evidence goes on the\nLEFT: this is a judging task, not an authoring one.\nRegistry items: venly-tokens, side-panel, timeline, field-list, status-pill,\nmoney, data-table; blocks: console-decision (ConsoleDecisionPanel,\nEvidenceStack, DecisionForm, DualTimeline).\nHooks: useAccount, useParty, useWallets, useTransfers,\nuseVirtualBankAccounts, useVenlyMock (the trail reads the mock's event log).\nTwo timeline columns, not one feed: the decision chain (who decided what, when,\nin which seat) beside money movement on the same subject. Different actors,\ndifferent audiences; merging them is what makes an audit trail unreadable.\nStates that must exist: loading, evidence present, evidence unavailable, decision owed, decision applied, stale decision, terminal decision, frozen, empty trail.\nRules that must hold: every evidence row is either a real field path or a\nlabelled omission, and an omission is a FIRST-CLASS type in the component's\nprops, so a placeholder cannot be rendered where a gap belongs;\nomission copy states only what is verified and never implies a result, a\npending state, or a clean one - and never mentions the API contract, which is\ndeveloper diagnostics rather than operator language; a field the API cannot\ncarry is captured anyway when the work needs it, and rendered with a visible\nbadge saying it is a console note rather than API state; every decision carries the\noptimistic-locking version, and a conflict means refetch and re-decide against\nfresh state, never auto-retry; every transition the console causes leaves a\ntimeline node with actor, role and a timezone-qualified absolute timestamp, so a\nstatus change with no node is a bug; a store resync is a system line, not a\ndecision node; the panel footer carries row-stepping key chips so the reviewer\nmoves row to row without closing.";
|
|
26
|
+
readonly "console-pricing-config": "# Console pricing configuration\nShell: in-shell content column. A config screen, not a queue: no whose-move\nvalue and no aging. The whole screen sits inside a platform-view section\nboundary - fee configuration is the platform's seat.\nRegistry items: venly-tokens, data-table, arithmetic-ladder, field-list,\nlist-error; blocks: console-pricing (ConsolePricingTable, FeeLadder, FeePanel\n- read-only, because the fees operation is GET-only; the panel renders\nfields, never an editable form).\nHooks: useCompanyFees.\nBinding: the fee data the packages actually serve is a VOLUME-TIER model - tier\nname, ramp direction, minimum and maximum volume, percentage, version - and it\nis the same model the shipped withdrawal quote consumes, so this screen shows\nwhere a real quote comes from. A second, richer per-rail configuration model\nexists on an internal plane and is NOT served here; it renders as a labelled\nomission, never as an empty form.\nStates that must exist: loading, tiers present, no tiers, configuration unavailable, worked example, save failed.\nRules that must hold: a worked arithmetic ladder is mandatory on the tier\nsection - a sample amount times the tier percentage, with the operator glyphs in\na left gutter - because a pricing screen that shows only stored numbers teaches\nnothing; the ladder renders ONLY over data that exists, never over the omitted\nsection; the tier\na sample amount falls into is highlighted in the table so the row and the ladder\nare visibly the same fact; a single-member enum renders as a disabled\nsingle-value field that says so, not a select pretending at choice; a date\nwindow that has not opened reads scheduled, never active; forms are single\ncolumn with the field width capped, label above input, helper text between them\nand the error below.";
|
|
27
|
+
readonly "console-simulator": "# Sandbox simulator (play the counterparty)\nShell: its own chrome - a scrimmed right-hand drawer on a distinct surface with\na persistent sandbox label, reachable from ONE fixed affordance in the top bar.\nIt is the only scrimmed drawer in the console, so the surface change alone\nsignals the register change.\nRegistry items: venly-tokens, field-list, status-pill, money; blocks:\nconsole-simulator (SimulatorDrawer, SimulatorControl, LedgerVerifyPanel,\nChannelFooter - SimulatorControl refuses an imperative operator-decision\nlabel with a thrown developer error).\nHooks: useVenlyMock. Every control maps to exactly one call on the mock's\nsimulations namespace - no control without a call, and no call renamed.\nBinding: inbound credits, provider progression and screening verdicts are things\nOTHER parties do, so they live here rather than in the operator's workflow.\nStates that must exist: drawer closed, drawer open, sharing, not sharing, credit landed, verdict returned, payout advanced, books balanced, books do not balance, reset.\nRules that must hold: controls are phrased as events that happen to you, in the\nthird person, while operator controls elsewhere are imperative decisions - a\ncontrol phrased in the wrong voice is in the wrong surface; a simulated\ntransition emits the SAME event the real path emits, and the trail attributes it\nto the simulator plainly rather than to an operator; the drawer is reachable\nonly from the top bar, never from a queue row or a decision panel, because those\npaths make another party's action look like the operator's; the ledger check gets\na visible surface: it is the one control here that asserts something true, namely\nthat the simulated books balance; the channel footer states the adapter, session\nand peer count, and says IN WORDS when the surface is not actually sharing - the\ndefault channel shares nothing and cross-context sharing is same-origin only, so\nwithout that line a two-context demo can prove nothing while looking correct.";
|
|
28
|
+
readonly "console-webhooks": "# Console webhooks (endpoint registration, honestly bounded)\nShell: in-shell content column - a table with a panel form beside it. This\none IS a form: the public plane carries the full lifecycle (list, create,\nread, replace, delete, ping).\nRegistry items: venly-tokens, data-table, status-pill, list-error; blocks:\nconsole-webhooks (WebhooksTable, WebhookForm, WebhookDeliveryLog - the\ndelivery log renders inside SIMULATOR chrome only, never on this screen).\nHooks: useWebhooks, useWebhook, useCreateWebhook, useUpdateWebhook,\nuseDeleteWebhook, usePingWebhook.\nBinding: webhook rows render the contract fields verbatim - url, name, and\na status enum that has exactly one member in this release, rendered as a\ndisabled single value that says so rather than a select pretending at\nchoice. The authentication method is a two-variant choice (API key or\nbasic); its secret fields are write-only on the contract, so the platform\nnever returns a stored secret and this screen never displays one - editing\nmeans re-entering the credential, and the form says why.\nStates that must exist: loading, webhooks listed, no webhooks yet, registration form, secret masked, ping result, delete confirmation, list error.\nRules that must hold: Ping is the promoted per-row affordance - it is the\none real signal the API offers about an endpoint - and its result renders\nverbatim; delivery history is NOT available from the API in this release\nand the screen says so on the screen itself, with the next step (use Ping),\nnever as a silent gap; the create operation carries no idempotency\nenvelope, so a replayed create registers a second webhook - any\nretry-safety a surface adds is a client-side convention badged as such,\nnever presented as contract behaviour; delete is confirm-and-explain: the\nconfirmation names the consequence before anything is removed; the\nsimulated delivery log is a sandbox surface phrased in the third person\nand badged as simulation, rendered only inside the simulator's own chrome.";
|
|
28
29
|
};
|
|
29
30
|
type JourneyKey = keyof typeof JOURNEYS;
|
|
30
31
|
interface Finding {
|
package/dist/frontend.js
CHANGED
|
@@ -37,12 +37,45 @@ Registry items: venly-tokens, field-list; block: receive.
|
|
|
37
37
|
Hooks: useVirtualBankAccounts (first active EUR account).
|
|
38
38
|
States that must exist: no virtual bank account yet (offer creation), details present, reference not yet assigned ("Not assigned yet" + Required pill - never "(not required)").
|
|
39
39
|
Rules that must hold: the payment reference is enforced as mandatory (amber Required pill, warning above the fields); per-field copy names the field it copied and only confirms on a successful write; rows never vanish - render the "(not required)" variant.`,
|
|
40
|
-
send: `# Send
|
|
41
|
-
Shell: full page;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
send: `# Send (one door)
|
|
41
|
+
Shell: full page; the door is the recipient picker; forms clamp ~600px; the
|
|
42
|
+
review and the step-up ceremony replace the form in place.
|
|
43
|
+
Registry items: venly-tokens, status-pill, field-list, data-table, list-error;
|
|
44
|
+
blocks: send (SendDoor, RecipientPicker, DirectoryPick, PlatformTransferFlow,
|
|
45
|
+
PayoutSendFlow, SendReview, StepUpConfirm, TransferDetail, PayoutDetail) and
|
|
46
|
+
recipients (RecipientsView, AddRecipientForm, BeneficiaryAccountForm,
|
|
47
|
+
RouteCeremony) - the prerequisite surface saved recipients are managed on.
|
|
48
|
+
Hooks: useCreateFiatTransfer and useCreateCryptoTransfer (the staged-transfer
|
|
49
|
+
machine typed per rail), useRequestPayout, usePartyRoles, useAddPartyRole,
|
|
50
|
+
useCreateParty, useRegisterPayoutBankAccount, useCreatePayoutRoute,
|
|
51
|
+
usePreparePayoutOwnershipProof, useCompletePayoutOwnershipProof, useParties,
|
|
52
|
+
useAccounts, useWallets, useAccountSupportedAssets, useTransfers, useTransfer,
|
|
53
|
+
usePayouts, usePayout, usePayoutRoutes.
|
|
54
|
+
Binding: ONE door - the first screen is the recipient picker and the fork is
|
|
55
|
+
the recipient's OBJECT TYPE, never a rail choice. A person or business on the
|
|
56
|
+
platform (a directory YOUR user table serves; render name + handle, never a
|
|
57
|
+
UUID - ids stay request-side) starts an on-platform transfer. A saved
|
|
58
|
+
recipient - a party holding the payout-recipient role, owning reviewed bank
|
|
59
|
+
accounts (details masked server-side) and an ACTIVE payout route - starts a
|
|
60
|
+
third-party payout referencing the ROUTE, never raw bank details. Your own
|
|
61
|
+
bank account is a link row into the withdraw flow. Send-to-external-wallet
|
|
62
|
+
has NO surface: no teaser, no disabled row, no rendered trace.
|
|
63
|
+
States that must exist: recipient picker (three classes, populated and empty), disabled with the reason (unverified directory rows, non-active routes and non-active accounts), over-balance, review (known figures only), step-up (wrong code blocks, the deterministic demo code proceeds), pending, completed, failed (the record's own error verbatim, terminal), requested, sending, provider processing, rejected, returned (money came back - a neutral terminal), no active route (blocked start with the unblocking CTA), load failure (explicit error plus retry - never an empty detail).
|
|
64
|
+
Rules that must hold: every money confirm passes the step-up ceremony against
|
|
65
|
+
YOUR auth adapter and the commit fires only after the code verifies - this is
|
|
66
|
+
app-side ceremony and must never be presented as an API security guarantee;
|
|
67
|
+
execution is single-shot on an idempotency key minted ONCE per staged draft,
|
|
68
|
+
so a retry replays the same record instead of moving money twice; reviews
|
|
69
|
+
render ONLY figures the API has produced, and the payout review states the
|
|
70
|
+
absence in words beside the two-sided units sentence. Forbidden to invent
|
|
71
|
+
(render the labelled omission or nothing at all): a fee row - and equally a
|
|
72
|
+
"No fee" claim, since no source confirms zero; an ETA or delivery date - no
|
|
73
|
+
timing field exists on transfers or payouts; a pre-create rate or
|
|
74
|
+
recipient-gets figure - exchangeRate and settledFiatAmount exist on CREATED
|
|
75
|
+
and COMPLETED records only; named in-flight stages beyond the status enums -
|
|
76
|
+
render the app-side observation log instead. Beneficiary details come back
|
|
77
|
+
masked: render the mask, never re-ask. Route states render verbatim and a
|
|
78
|
+
REJECTED route is terminal-negative with a way forward, never a dead end.`,
|
|
46
79
|
activity: `# Activity
|
|
47
80
|
Shell: full-width table + side panel.
|
|
48
81
|
Registry items: venly-tokens, data-table, status-pill, side-panel, timeline; block: activity.
|
|
@@ -83,8 +116,10 @@ Rules that must hold: the optimistic-locking version travels with every decision
|
|
|
83
116
|
Shell: left nav rail + thin top bar, full-width content, and a page-edge
|
|
84
117
|
environment banner naming mock mode. Not a consumer surface - density rules
|
|
85
118
|
apply.
|
|
86
|
-
Registry items: venly-tokens, data-table, status-pill, money, list-error
|
|
87
|
-
|
|
119
|
+
Registry items: venly-tokens, data-table, status-pill, money, list-error;
|
|
120
|
+
blocks: console-queue (ConsoleQueue, WhoseMove, AgeCell, deriveKycActor,
|
|
121
|
+
derivePayoutActor - the derivation functions are exported so a consumer can
|
|
122
|
+
unit-test the join).
|
|
88
123
|
Hooks: useAccounts, useParties. The queue's own state is DERIVED on every
|
|
89
124
|
render - never stored, never cached as a status.
|
|
90
125
|
Binding: sections are ACTORS, not statuses - your move, waiting on the customer,
|
|
@@ -109,7 +144,8 @@ visible clipped at the panel edge and the source row stays tinted. Escalate to a
|
|
|
109
144
|
35/65 split only when the evidence outgrows the panel. Evidence goes on the
|
|
110
145
|
LEFT: this is a judging task, not an authoring one.
|
|
111
146
|
Registry items: venly-tokens, side-panel, timeline, field-list, status-pill,
|
|
112
|
-
money, data-table
|
|
147
|
+
money, data-table; blocks: console-decision (ConsoleDecisionPanel,
|
|
148
|
+
EvidenceStack, DecisionForm, DualTimeline).
|
|
113
149
|
Hooks: useAccount, useParty, useWallets, useTransfers,
|
|
114
150
|
useVirtualBankAccounts, useVenlyMock (the trail reads the mock's event log).
|
|
115
151
|
Two timeline columns, not one feed: the decision chain (who decided what, when,
|
|
@@ -132,8 +168,12 @@ decision node; the panel footer carries row-stepping key chips so the reviewer
|
|
|
132
168
|
moves row to row without closing.`,
|
|
133
169
|
"console-pricing-config": `# Console pricing configuration
|
|
134
170
|
Shell: in-shell content column. A config screen, not a queue: no whose-move
|
|
135
|
-
value and no aging.
|
|
136
|
-
|
|
171
|
+
value and no aging. The whole screen sits inside a platform-view section
|
|
172
|
+
boundary - fee configuration is the platform's seat.
|
|
173
|
+
Registry items: venly-tokens, data-table, arithmetic-ladder, field-list,
|
|
174
|
+
list-error; blocks: console-pricing (ConsolePricingTable, FeeLadder, FeePanel
|
|
175
|
+
- read-only, because the fees operation is GET-only; the panel renders
|
|
176
|
+
fields, never an editable form).
|
|
137
177
|
Hooks: useCompanyFees.
|
|
138
178
|
Binding: the fee data the packages actually serve is a VOLUME-TIER model - tier
|
|
139
179
|
name, ramp direction, minimum and maximum volume, percentage, version - and it
|
|
@@ -158,7 +198,10 @@ Shell: its own chrome - a scrimmed right-hand drawer on a distinct surface with
|
|
|
158
198
|
a persistent sandbox label, reachable from ONE fixed affordance in the top bar.
|
|
159
199
|
It is the only scrimmed drawer in the console, so the surface change alone
|
|
160
200
|
signals the register change.
|
|
161
|
-
Registry items: venly-tokens, field-list, status-pill, money
|
|
201
|
+
Registry items: venly-tokens, field-list, status-pill, money; blocks:
|
|
202
|
+
console-simulator (SimulatorDrawer, SimulatorControl, LedgerVerifyPanel,
|
|
203
|
+
ChannelFooter - SimulatorControl refuses an imperative operator-decision
|
|
204
|
+
label with a thrown developer error).
|
|
162
205
|
Hooks: useVenlyMock. Every control maps to exactly one call on the mock's
|
|
163
206
|
simulations namespace - no control without a call, and no call renamed.
|
|
164
207
|
Binding: inbound credits, provider progression and screening verdicts are things
|
|
@@ -176,68 +219,135 @@ that the simulated books balance; the channel footer states the adapter, session
|
|
|
176
219
|
and peer count, and says IN WORDS when the surface is not actually sharing - the
|
|
177
220
|
default channel shares nothing and cross-context sharing is same-origin only, so
|
|
178
221
|
without that line a two-context demo can prove nothing while looking correct.`,
|
|
222
|
+
"console-webhooks": `# Console webhooks (endpoint registration, honestly bounded)
|
|
223
|
+
Shell: in-shell content column - a table with a panel form beside it. This
|
|
224
|
+
one IS a form: the public plane carries the full lifecycle (list, create,
|
|
225
|
+
read, replace, delete, ping).
|
|
226
|
+
Registry items: venly-tokens, data-table, status-pill, list-error; blocks:
|
|
227
|
+
console-webhooks (WebhooksTable, WebhookForm, WebhookDeliveryLog - the
|
|
228
|
+
delivery log renders inside SIMULATOR chrome only, never on this screen).
|
|
229
|
+
Hooks: useWebhooks, useWebhook, useCreateWebhook, useUpdateWebhook,
|
|
230
|
+
useDeleteWebhook, usePingWebhook.
|
|
231
|
+
Binding: webhook rows render the contract fields verbatim - url, name, and
|
|
232
|
+
a status enum that has exactly one member in this release, rendered as a
|
|
233
|
+
disabled single value that says so rather than a select pretending at
|
|
234
|
+
choice. The authentication method is a two-variant choice (API key or
|
|
235
|
+
basic); its secret fields are write-only on the contract, so the platform
|
|
236
|
+
never returns a stored secret and this screen never displays one - editing
|
|
237
|
+
means re-entering the credential, and the form says why.
|
|
238
|
+
States that must exist: loading, webhooks listed, no webhooks yet, registration form, secret masked, ping result, delete confirmation, list error.
|
|
239
|
+
Rules that must hold: Ping is the promoted per-row affordance - it is the
|
|
240
|
+
one real signal the API offers about an endpoint - and its result renders
|
|
241
|
+
verbatim; delivery history is NOT available from the API in this release
|
|
242
|
+
and the screen says so on the screen itself, with the next step (use Ping),
|
|
243
|
+
never as a silent gap; the create operation carries no idempotency
|
|
244
|
+
envelope, so a replayed create registers a second webhook - any
|
|
245
|
+
retry-safety a surface adds is a client-side convention badged as such,
|
|
246
|
+
never presented as contract behaviour; delete is confirm-and-explain: the
|
|
247
|
+
confirmation names the consequence before anything is removed; the
|
|
248
|
+
simulated delivery log is a sandbox surface phrased in the third person
|
|
249
|
+
and badged as simulation, rendered only inside the simulator's own chrome.`,
|
|
179
250
|
};
|
|
180
251
|
const JOURNEY_KEYS = Object.keys(JOURNEYS);
|
|
181
252
|
const RUNTIME_PACKAGES_BY_BLOCK = {
|
|
182
253
|
activity: {
|
|
183
|
-
"@venlyfinance/react": "^0.
|
|
184
|
-
"@venlyfinance/sdk": "^0.
|
|
254
|
+
"@venlyfinance/react": "^0.6.0",
|
|
255
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
185
256
|
"@tanstack/react-query": "^5.0.0",
|
|
186
257
|
},
|
|
187
258
|
auth: { "@radix-ui/react-one-time-password-field": "^0.1.16" },
|
|
188
259
|
balances: {
|
|
189
|
-
"@venlyfinance/react": "^0.
|
|
190
|
-
"@venlyfinance/sdk": "^0.
|
|
260
|
+
"@venlyfinance/react": "^0.6.0",
|
|
261
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
191
262
|
"@tanstack/react-query": "^5.0.0",
|
|
192
263
|
},
|
|
193
264
|
"bank-accounts": {
|
|
194
|
-
"@venlyfinance/react": "^0.
|
|
195
|
-
"@venlyfinance/sdk": "^0.
|
|
265
|
+
"@venlyfinance/react": "^0.6.0",
|
|
266
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
267
|
+
"@tanstack/react-query": "^5.0.0",
|
|
268
|
+
},
|
|
269
|
+
"console-decision": {
|
|
270
|
+
"@venlyfinance/react": "^0.6.0",
|
|
271
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
272
|
+
"@tanstack/react-query": "^5.0.0",
|
|
273
|
+
},
|
|
274
|
+
"console-queue": {
|
|
275
|
+
"@venlyfinance/react": "^0.6.0",
|
|
276
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
277
|
+
"@tanstack/react-query": "^5.0.0",
|
|
278
|
+
},
|
|
279
|
+
"console-pricing": {
|
|
280
|
+
"@venlyfinance/react": "^0.6.0",
|
|
281
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
282
|
+
"@tanstack/react-query": "^5.0.0",
|
|
283
|
+
},
|
|
284
|
+
"console-simulator": {
|
|
285
|
+
"@venlyfinance/react": "^0.6.0",
|
|
286
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
287
|
+
"@tanstack/react-query": "^5.0.0",
|
|
288
|
+
},
|
|
289
|
+
"console-tenant": {
|
|
290
|
+
"@venlyfinance/react": "^0.6.0",
|
|
291
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
292
|
+
"@tanstack/react-query": "^5.0.0",
|
|
293
|
+
},
|
|
294
|
+
"console-webhooks": {
|
|
295
|
+
"@venlyfinance/react": "^0.6.0",
|
|
296
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
196
297
|
"@tanstack/react-query": "^5.0.0",
|
|
197
298
|
},
|
|
198
299
|
onboarding: {
|
|
199
|
-
"@venlyfinance/react": "^0.
|
|
200
|
-
"@venlyfinance/sdk": "^0.
|
|
300
|
+
"@venlyfinance/react": "^0.6.0",
|
|
301
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
201
302
|
"@tanstack/react-query": "^5.0.0",
|
|
202
303
|
},
|
|
203
304
|
receive: {
|
|
204
|
-
"@venlyfinance/react": "^0.
|
|
205
|
-
"@venlyfinance/sdk": "^0.
|
|
305
|
+
"@venlyfinance/react": "^0.6.0",
|
|
306
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
206
307
|
"@tanstack/react-query": "^5.0.0",
|
|
207
308
|
},
|
|
208
309
|
reconciliation: {
|
|
209
|
-
"@venlyfinance/react": "^0.
|
|
210
|
-
"@venlyfinance/sdk": "^0.
|
|
310
|
+
"@venlyfinance/react": "^0.6.0",
|
|
311
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
312
|
+
"@tanstack/react-query": "^5.0.0",
|
|
313
|
+
},
|
|
314
|
+
recipients: {
|
|
315
|
+
"@venlyfinance/react": "^0.6.0",
|
|
316
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
211
317
|
"@tanstack/react-query": "^5.0.0",
|
|
212
318
|
},
|
|
213
319
|
send: {
|
|
214
|
-
"@venlyfinance/react": "^0.
|
|
215
|
-
"@venlyfinance/sdk": "^0.
|
|
320
|
+
"@venlyfinance/react": "^0.6.0",
|
|
321
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
216
322
|
"@tanstack/react-query": "^5.0.0",
|
|
323
|
+
"@radix-ui/react-one-time-password-field": "^0.1.16",
|
|
217
324
|
},
|
|
218
325
|
team: { "@radix-ui/react-dialog": "^1.1.23" },
|
|
219
326
|
withdraw: {
|
|
220
|
-
"@venlyfinance/react": "^0.
|
|
221
|
-
"@venlyfinance/sdk": "^0.
|
|
327
|
+
"@venlyfinance/react": "^0.6.0",
|
|
328
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
222
329
|
"@tanstack/react-query": "^5.0.0",
|
|
223
330
|
},
|
|
224
331
|
};
|
|
225
332
|
/**
|
|
333
|
+
* Kept in step with the ranges the registry generator stamps into ui/r/*.json
|
|
334
|
+
* (`RUNTIME_DEPENDENCIES` in ui/scripts/build-registry.mjs): the runtime-contract
|
|
335
|
+
* test asserts the two agree, so a blueprint can never advertise a range the
|
|
336
|
+
* registry will not install.
|
|
337
|
+
*
|
|
226
338
|
* The package set any hook-using screen needs, for journeys the registry has no
|
|
227
|
-
* composite block for yet -
|
|
339
|
+
* composite block for yet - those screens are built from primitives
|
|
228
340
|
* (data-table, side-panel, timeline …), and a primitive registry item declares
|
|
229
341
|
* no npm dependencies, so deriving `requiredPackages` from blocks alone would
|
|
230
342
|
* tell an agent that a surface living entirely on hooks needs no packages.
|
|
231
343
|
*
|
|
232
|
-
* The
|
|
233
|
-
*
|
|
234
|
-
* 0.6.0
|
|
235
|
-
* ui/package.json, which is older; a console screen built against that range
|
|
236
|
-
* would describe states it cannot reach.
|
|
344
|
+
* The ranges name the versions the console surfaces actually consume: the
|
|
345
|
+
* party IV read and the payout hooks arrived in sdk 0.7.0 / react 0.6.0, on
|
|
346
|
+
* top of the 0.6.0 mock behaviours (channel state, balances that move).
|
|
237
347
|
*/
|
|
238
348
|
const DATA_PLANE_PACKAGES = {
|
|
239
|
-
"@venlyfinance/react": "^0.
|
|
240
|
-
"@venlyfinance/sdk": "^0.
|
|
349
|
+
"@venlyfinance/react": "^0.6.0",
|
|
350
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
241
351
|
"@tanstack/react-query": "^5.0.0",
|
|
242
352
|
};
|
|
243
353
|
const JOURNEY_RUNTIME = {
|
|
@@ -253,7 +363,37 @@ const JOURNEY_RUNTIME = {
|
|
|
253
363
|
},
|
|
254
364
|
"home-balances": { blocks: ["balances"], hooks: ["useAccounts", "useWallets"] },
|
|
255
365
|
receive: { blocks: ["receive"], hooks: ["useVirtualBankAccounts"] },
|
|
256
|
-
send: {
|
|
366
|
+
send: {
|
|
367
|
+
blocks: ["send", "recipients"],
|
|
368
|
+
hooks: [
|
|
369
|
+
"useCreateFiatTransfer",
|
|
370
|
+
"useCreateCryptoTransfer",
|
|
371
|
+
"useRequestPayout",
|
|
372
|
+
"usePartyRoles",
|
|
373
|
+
"useAddPartyRole",
|
|
374
|
+
"useCreateParty",
|
|
375
|
+
"useRegisterPayoutBankAccount",
|
|
376
|
+
"useCreatePayoutRoute",
|
|
377
|
+
"usePreparePayoutOwnershipProof",
|
|
378
|
+
"useCompletePayoutOwnershipProof",
|
|
379
|
+
"useParties",
|
|
380
|
+
"useAccounts",
|
|
381
|
+
"useWallets",
|
|
382
|
+
"useAccountSupportedAssets",
|
|
383
|
+
"useTransfers",
|
|
384
|
+
"useTransfer",
|
|
385
|
+
"usePayouts",
|
|
386
|
+
"usePayout",
|
|
387
|
+
"usePayoutRoutes",
|
|
388
|
+
],
|
|
389
|
+
extraForbidden: [
|
|
390
|
+
"a fee row or a \"No fee\" claim (no source confirms zero)",
|
|
391
|
+
"an ETA or delivery-date row (no timing field exists on transfers or payouts)",
|
|
392
|
+
"a pre-create rate or recipient-gets figure (exchangeRate/settledFiatAmount are post-create fields)",
|
|
393
|
+
"named in-flight stages beyond the status enums (render the observation log instead)",
|
|
394
|
+
"a send-to-external-wallet surface (no teaser, no disabled row, no rendered trace)",
|
|
395
|
+
],
|
|
396
|
+
},
|
|
257
397
|
activity: { blocks: ["activity"], hooks: ["useTransfers", "useRampRequests"] },
|
|
258
398
|
"onboarding-status": {
|
|
259
399
|
blocks: ["onboarding"],
|
|
@@ -286,8 +426,7 @@ const JOURNEY_RUNTIME = {
|
|
|
286
426
|
hooks: ["useRampRequests", "useFourEyesApproval", "useRampLifecycle"],
|
|
287
427
|
},
|
|
288
428
|
"console-review-queue": {
|
|
289
|
-
blocks: [],
|
|
290
|
-
registryItems: ["venly-tokens", "data-table", "status-pill", "money", "list-error"],
|
|
429
|
+
blocks: ["console-queue"],
|
|
291
430
|
dataPlane: true,
|
|
292
431
|
hooks: ["useAccounts", "useParties"],
|
|
293
432
|
extraForbidden: [
|
|
@@ -297,16 +436,7 @@ const JOURNEY_RUNTIME = {
|
|
|
297
436
|
],
|
|
298
437
|
},
|
|
299
438
|
"console-decision-detail": {
|
|
300
|
-
blocks: [],
|
|
301
|
-
registryItems: [
|
|
302
|
-
"venly-tokens",
|
|
303
|
-
"side-panel",
|
|
304
|
-
"timeline",
|
|
305
|
-
"field-list",
|
|
306
|
-
"status-pill",
|
|
307
|
-
"money",
|
|
308
|
-
"data-table",
|
|
309
|
-
],
|
|
439
|
+
blocks: ["console-decision"],
|
|
310
440
|
dataPlane: true,
|
|
311
441
|
hooks: [
|
|
312
442
|
"useAccount",
|
|
@@ -324,18 +454,17 @@ const JOURNEY_RUNTIME = {
|
|
|
324
454
|
],
|
|
325
455
|
},
|
|
326
456
|
"console-pricing-config": {
|
|
327
|
-
blocks: [],
|
|
328
|
-
registryItems: ["venly-tokens", "data-table", "arithmetic-ladder", "field-list"],
|
|
457
|
+
blocks: ["console-pricing"],
|
|
329
458
|
dataPlane: true,
|
|
330
459
|
hooks: ["useCompanyFees"],
|
|
331
460
|
extraForbidden: [
|
|
332
461
|
"an arithmetic ladder over figures the API does not serve",
|
|
333
462
|
"a single-member enum rendered as a select",
|
|
463
|
+
"an editable control on the tier section (the fees operation is GET-only)",
|
|
334
464
|
],
|
|
335
465
|
},
|
|
336
466
|
"console-simulator": {
|
|
337
|
-
blocks: [],
|
|
338
|
-
registryItems: ["venly-tokens", "field-list", "status-pill", "money"],
|
|
467
|
+
blocks: ["console-simulator"],
|
|
339
468
|
dataPlane: true,
|
|
340
469
|
hooks: ["useVenlyMock"],
|
|
341
470
|
extraForbidden: [
|
|
@@ -345,6 +474,24 @@ const JOURNEY_RUNTIME = {
|
|
|
345
474
|
"a cross-context demo that does not state its channel adapter and peer count",
|
|
346
475
|
],
|
|
347
476
|
},
|
|
477
|
+
"console-webhooks": {
|
|
478
|
+
blocks: ["console-webhooks"],
|
|
479
|
+
dataPlane: true,
|
|
480
|
+
hooks: [
|
|
481
|
+
"useWebhooks",
|
|
482
|
+
"useWebhook",
|
|
483
|
+
"useCreateWebhook",
|
|
484
|
+
"useUpdateWebhook",
|
|
485
|
+
"useDeleteWebhook",
|
|
486
|
+
"usePingWebhook",
|
|
487
|
+
],
|
|
488
|
+
extraForbidden: [
|
|
489
|
+
"a delivery-history surface presented as API-served (no delivery-log operation exists on any plane)",
|
|
490
|
+
"a stored secret displayed anywhere (the authentication secret fields are write-only)",
|
|
491
|
+
"retry-safety presented as contract behaviour (a replayed create registers a second webhook)",
|
|
492
|
+
"the single-member status enum rendered as a select",
|
|
493
|
+
],
|
|
494
|
+
},
|
|
348
495
|
};
|
|
349
496
|
const RUNTIME_CONTRACT_SCHEMA = z.object({
|
|
350
497
|
runtimeMode: z.enum(["mock", "staging", "production"]),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venlyfinance/settlement-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Venly Finance MCP: SDK-backed tools, resources and prompts for building international money products safely.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"node": ">=20"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@venlyfinance/sdk": "^0.
|
|
32
|
+
"@venlyfinance/sdk": "^0.7.0",
|
|
33
33
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
34
34
|
"zod": "^3.23.8"
|
|
35
35
|
},
|