@stelis/say-ur-intent 0.0.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.
@@ -0,0 +1,234 @@
1
+ # Frontend Policy
2
+
3
+ Say Ur Intent frontend pages are local review and wallet-context surfaces. They
4
+ exist to show server-validated facts, capture explicit wallet gestures, and
5
+ keep AI reasoning separate from wallet authority.
6
+
7
+ The current release ships the wallet identity page, local settings page, and a
8
+ blocked or non-signable review page that can display server-computed review state.
9
+ The review server may build local unsigned DeepBook swap transaction material
10
+ during account-bound review, but the frontend does not receive transaction
11
+ bytes outside the digest-gated handoff. The review page offers a sign action
12
+ only on a `ready_for_wallet_review` state whose wallet account matches the
13
+ reviewed account; it never builds transactions in the frontend.
14
+
15
+ ## Role
16
+
17
+ Current release frontend surfaces may capture wallet identity, display review
18
+ state, and request refresh when allowed. They do not submit wallet signatures or
19
+ execution results.
20
+
21
+ It is not a trading dashboard, AI chat, portfolio app, alert surface, analytics screen, or safety oracle.
22
+
23
+ ## Display Priority
24
+
25
+ Show the minimum facts needed for the user's decision first:
26
+
27
+ 1. What is happening?
28
+ 2. Can the user proceed?
29
+ 3. What happens if the user proceeds?
30
+ 4. What is the next action?
31
+
32
+ Technical details belong behind compact details controls. Raw protocol data must not dominate the primary screen.
33
+
34
+ ## Information Source
35
+
36
+ Primary UI may render only server-validated structured data. AI-generated interpretation must not appear as trusted review fact.
37
+
38
+ The frontend must not compute quote truth, readiness, blocked status, safety, or
39
+ final execution truth. In the current release, it may render state, connect a
40
+ wallet, ask the server to refresh, and revoke wallet identity when that action
41
+ exists. Wallet or signing result submission is not a current-release frontend
42
+ capability.
43
+
44
+ ## Wallet Identity
45
+
46
+ Wallet identity is the product path for active-account reads and account-bound review. Manual address entry is not a product path for the review UI or wallet identity flow. MCP explicit-address inputs for public coin balance snapshots are separate read-only tool inputs and do not create active account context.
47
+
48
+ Sender-independent DeepBook market reads do not require wallet identity. Wallet identity capture is not signing authorization.
49
+
50
+ The user must be able to see the active wallet account when connected.
51
+
52
+ Reusable identity sessions may set an ambient read context after the user connects a wallet. This read context remains until the user clears it or replaces it with another wallet identity. It must be presented as active account context, not login, signing authorization, custody, or permission for transactions.
53
+
54
+ When a wallet exposes multiple accounts, Say Ur Intent captures the account returned by the wallet connection result. The UI must display that account clearly. Choosing a different account requires replacing the active account context with another wallet identity connection.
55
+
56
+ ## Review Surface
57
+
58
+ Each action review is a separate ceremony. The review screen prioritizes asset flow over protocol internals.
59
+
60
+ Required primary facts:
61
+
62
+ - action summary
63
+ - send amount
64
+ - expected receive or minimum receive
65
+ - current review status
66
+ - next action
67
+
68
+ When a user can spend more than the displayed send amount, the top-level asset flow must show the spend limit with explicit language such as `up to`. Do not hide max spend in secondary details when it changes the user's decision.
69
+
70
+ `assetFlowPreview` entries with `amountKind: "display_intent"` are display-only proposal facts. They are different from review-time `assetFlowActual`, simulation summaries, and balance changes, and the frontend must not use them as signing input, minimum receive, or transaction-building input.
71
+
72
+ When a plan includes `reviewModel`, the review page must show the external
73
+ proposal source, proposed action, asset flow, recipient or target, freshness,
74
+ missing evidence, required user choices, unsupported claims, blocking checks,
75
+ and `nonSignableReason`. These fields are review annotations only. They are not
76
+ transaction material. They are not route selection or settlement-token
77
+ selection. They are not wallet readiness, signing readiness, or execution
78
+ safety.
79
+
80
+ In the current release, the review page may create a wallet identity session, reload the active account context, and request account-bound review computation.
81
+
82
+ It renders server-returned review checks for the resolved direct pool, raw quote evidence, quote freshness, derived raw min-out policy, DEEP fee raw evidence, and internal digest commitment.
83
+ It may also render a server-returned check that local unsigned DeepBook swap
84
+ transaction material was built and kept internal to the review server.
85
+ It may render `reviewState.humanReadableReview` when the server returns it. That
86
+ summary is displayable review evidence projected from server-verified private
87
+ review artifacts. The frontend must not recompute its quote truth, object
88
+ ownership, freshness, blocked status, or readiness.
89
+ It may render `reviewState.simulation` when the server returns it. That summary
90
+ is a redacted projection from private review-time simulation evidence for stored
91
+ local transaction material. The frontend must not recompute simulation truth.
92
+ The frontend must not extract transaction bytes or a public digest from it.
93
+ The frontend must not treat it as wallet readiness or signing readiness.
94
+ The frontend must not treat it as execution readiness or proof of wallet
95
+ submission.
96
+
97
+ It must keep those checks as review evidence only.
98
+ It must not treat them as public transaction bytes, wallet readiness, signing readiness, route quality, or execution safety.
99
+
100
+ Compact secondary facts:
101
+
102
+ - venue or protocol
103
+ - quote timestamp
104
+ - gas estimate when available
105
+ - max spend when available
106
+
107
+ Details:
108
+
109
+ - pool ID
110
+ - package ID
111
+ - object changes
112
+ - balance changes
113
+ - simulation summary
114
+ - Review checks
115
+
116
+ Review checks are generally details. Failed checks and warning checks that determine the current `blocked` or `refresh_required` status must be elevated next to the status banner so the user can understand the reason without opening details.
117
+
118
+ If the server returns a `PtbVisualizationArtifact`, the frontend may render only
119
+ Mermaid flowchart text plus diagnostics. The panel must show the generated time,
120
+ source, diagnostics, and unsupported-use boundary when those fields are present.
121
+ It must not store or render executable transaction material, wallet signature
122
+ requests, private-key material, or arbitrary Move calls. A PTB graph is not a
123
+ sign action, not a transaction-building action, not a wallet readiness signal,
124
+ not a signing readiness signal, not a payment execution readiness signal, not a
125
+ route-quality signal, and not an execution-safety signal.
126
+
127
+ ## Current Release State Rules
128
+
129
+ The review page is a state wizard with three displayed steps (Review, Sign,
130
+ Result) over nine page states. Every state keeps the same constant layout: the
131
+ step indicator, a one-line state headline, the constant Transaction card
132
+ (plan-level values that fill in with reviewed values), the state-specific
133
+ block, and a collapsed Raw evidence card (audit record with a
134
+ copy-as-Markdown action). Only the current state's actions are rendered;
135
+ out-of-state buttons are removed, not disabled.
136
+
137
+ The sign action appears only on `ready_for_wallet_review` with an emitted
138
+ wallet review contract, a connected wallet whose account equals the reviewed
139
+ account, and a successful digest-gated handoff. The signing wallet list offers
140
+ only the wallet recorded for the active account; other detected wallets are
141
+ not offered. While a handoff is outstanding the server locks the session
142
+ (state recomputes are refused) and the page shows a signing-in-progress state
143
+ whose only action is cancel. Other states render:
144
+
145
+ - `refresh_required` and an expired quote: hide the sign action and show the
146
+ refresh action with the safe-funds copy.
147
+ - `blocked`: hide the sign action and show a human-readable reason plus the
148
+ retry action.
149
+ - recorded execution result: show the receipt card (status, digest, failure
150
+ reason) with no review or sign actions; the session is finished.
151
+ - `expired`: show expiration and a concrete restart path. The default restart path is to return to the AI client and request a new wallet identity or review session.
152
+
153
+ External proposal review sessions are non-signable. Their primary action is to
154
+ inspect the review facts and return to the AI client with any remaining user
155
+ choices.
156
+
157
+ ## Actions
158
+
159
+ Each state should expose at most one primary action.
160
+
161
+ The review page may show an account-bound review action when an active account is present and no review state has been recorded for the selected plan.
162
+
163
+ It may also show that action when the server status requires refreshed account-bound evidence.
164
+
165
+ That action asks the local review server to compute review state.
166
+ It is not a sign action, frontend transaction-building action, wallet readiness signal, signing readiness signal, or route-quality signal.
167
+
168
+ Do not show a quote/evidence refresh button unless the quote expired, the
169
+ status is `refresh_required`, or no review state has been recorded yet.
170
+
171
+ Do not automatically close tabs after terminal results. Do not silently renew identity sessions. Do not edit amount, slippage, target asset, or venue on the frontend; revisions go back through AI and MCP.
172
+
173
+ Loading and waiting states must use plain status copy. For wallet identity, use copy such as `Finish or cancel the request in your wallet popup`. For signing, keep the user's attention on the wallet popup and do not add extra choices.
174
+
175
+ If a terminal or unrecoverable frontend error occurs, show one clear message and one recovery route. Examples: invalid token, missing session, expired session, unsupported chain, or no compatible wallet.
176
+
177
+ ## Language
178
+
179
+ Use short, direct, non-promotional copy.
180
+
181
+ Do not say:
182
+
183
+ - safe
184
+ - recommended
185
+ - best
186
+ - guaranteed
187
+ - approved by AI
188
+
189
+ Prefer:
190
+
191
+ - ready for wallet review
192
+ - refresh required
193
+ - blocked
194
+ - expected receive
195
+ - minimum receive
196
+ - checked at
197
+
198
+ Source fields may keep protocol-facing names such as `fetchedAt`. Frontend labels should map them to user-facing copy such as `checked at`.
199
+
200
+ Frontend labels stay in English. Localization must preserve protocol names, token symbols, object IDs, package IDs, and reason enums without translation.
201
+
202
+ ## Security
203
+
204
+ Tokens must not be accepted in query strings. Wallet addresses must not be written to local event logs in plaintext. Private keys, signatures, transaction bytes, and arbitrary Move calls must not appear in frontend state.
205
+
206
+ CSP should prefer external assets and avoid inline script or inline style. Host, Origin, and session token validation are mandatory for state-changing APIs.
207
+
208
+ Wallet and review screens must be keyboard reachable and screen-reader labeled. Status and error changes must be exposed as text, not color alone.
209
+
210
+ Native push notifications are out of scope. A frontend may use low-authority browser affordances such as document title changes for off-tab terminal results, but only after server status changes.
211
+
212
+ Each session URL represents one independent tab surface. Cross-tab state sharing is out of scope unless a shared local store is explicitly designed.
213
+
214
+ ## Out Of Scope
215
+
216
+ The frontend must not add:
217
+
218
+ - price charts
219
+ - candlesticks
220
+ - portfolio dashboards
221
+ - AI chat
222
+ - trading recommendations
223
+ - alerts
224
+ - automatic transaction history dashboard pages
225
+ - multi-wallet comparison
226
+ - saved plans or bookmarks
227
+ - arbitrary strategy controls
228
+
229
+ The exclusions above target automatic, background-indexed, or
230
+ recommendation-style surfaces. A user-requested local record view — the
231
+ analysis page that shows a wallet asset snapshot at a fetched timestamp and
232
+ summaries of locally stored review and activity records — is a deliberately
233
+ sequenced roadmap surface, not part of these exclusions. That planned view must
234
+ still avoid P&L, valuation, performance, and tax claims, and must not add background indexing.
@@ -0,0 +1,85 @@
1
+ # Local DB Architecture
2
+
3
+ Say Ur Intent uses a local SQLite database for durable product state that must survive MCP server restarts. The database stores account read context, Say Ur Intent review activity evidence, and user-requested bounded Sui activity facts. It is not a custody store, wallet authorization store, background indexer, complete wallet-history store, or raw transaction archive.
4
+
5
+ This document is for maintainers and contributors who change local state, import/export behavior, activity queries, or review evidence storage. Product users normally need only the README and `docs/MCP_SETUP.md`.
6
+
7
+ ## Engine
8
+
9
+ The runtime uses the `better-sqlite3` npm package for normal SQLite file semantics and incremental writes. Users do not install a separate database server.
10
+
11
+ The package targets Node.js `>=22`. Node 22 or 24 LTS is recommended.
12
+
13
+ `better-sqlite3` is an npm dependency, not a separate product database installation. The pinned version is `12.9.0`. Standard macOS arm64/x64, Linux arm64/x64, and Windows x64 platforms normally use prebuilt binaries; less common platforms such as Windows arm64 can require a native build toolchain. The release check verifies that the driver can be imported, can create an in-memory database, and also works after installing the packed tarball.
14
+
15
+ ## File Location
16
+
17
+ On first start, the runtime creates a SQLite file named `say-ur-intent.sqlite` under the operating system's app data directory for Say Ur Intent.
18
+
19
+ The optional override is:
20
+
21
+ ```bash
22
+ export SAY_UR_INTENT_DATA_DIR="/path/to/local/app-data"
23
+ ```
24
+
25
+ Product docs, MCP responses, and tool outputs must not reveal a user's absolute database path. Use placeholders in documentation.
26
+
27
+ ## Open Policy
28
+
29
+ Every database connection applies:
30
+
31
+ ```sql
32
+ PRAGMA journal_mode=WAL;
33
+ PRAGMA synchronous=NORMAL;
34
+ PRAGMA foreign_keys=ON;
35
+ ```
36
+
37
+ Writes use SQLite's normal file-backed engine. On startup, the runtime creates the tables listed in [Tables](#tables) when the database file is empty.
38
+
39
+ Delete the local DB files or set a new `SAY_UR_INTENT_DATA_DIR` when resetting local product data files.
40
+
41
+ WAL mode can create companion files next to the main database, such as `say-ur-intent.sqlite-wal` and `say-ur-intent.sqlite-shm`. Backups and manual moves should keep those files together with the main database while the MCP server is stopped. Avoid placing `SAY_UR_INTENT_DATA_DIR` in cloud-synchronized folders such as iCloud Drive, Dropbox, or similar sync roots because WAL companion files can be copied out of order.
42
+
43
+ ## Tables
44
+
45
+ - `accounts`: normalized Sui account addresses and first/last use timestamps.
46
+ - `active_account_context`: a single-row read context. It can point to one active account or be cleared.
47
+ - `review_sessions`: review session header, current status, full action plan JSON, and materialized requested intent JSON when present.
48
+ - `review_state_snapshots`: append-only account-bound `ReviewState` snapshots with status and reason columns for queryability.
49
+ - `review_status_transitions`: append-only review lifecycle timing for funnel and review-timing analysis.
50
+ - `review_executions`: Say Ur Intent review execution result evidence, keyed by `review_session_id`.
51
+ - `external_activity_scans`: user-requested digest lookups, bounded account scans, or sent-function scans, including request window, endpoint host, chain identifier, continuation metadata, coverage signals, and internal scan-kind provenance.
52
+ - `external_activity_transactions`: normalized Sui transaction facts linked to a known local account and the first/last scan that observed them. The optional detail JSON stores typed facts such as capped Move call targets, raw balance changes, object changes, event summaries, gas raw cost fields, execution errors, and truncation flags when GraphQL returns them. Each stored detail JSON value is capped at 64 KiB.
53
+ - `local_settings`: allowlisted local settings. The current key set is `suiGrpcUrl` and `suiGraphqlUrl`, stored as JSON-encoded text and applied after restart.
54
+ - `coin_metadata_cache`: account-independent positive cache for Sui coin metadata used only to format wallet balance display amounts. Rows are keyed by normalized coin type and verified mainnet chain identifier, expire after 24 hours, and are excluded from local data export/import. Read or write failures for this cache block affected wallet unit reads with `metadata_cache_unavailable`; they are not reported as unavailable token decimals.
55
+
56
+ Database columns use snake_case. MCP and HTTP JSON fields use camelCase, so the database `review_session_id` column stores the same review-session identity exposed as `reviewSessionId` in API responses.
57
+
58
+ Table relationships:
59
+
60
+ - `active_account_context.account_id` and `review_sessions.account_id` point to `accounts.id` when an account is present.
61
+ - `review_state_snapshots`, `review_status_transitions`, and `review_executions` point to `review_sessions.id` through `review_session_id` and can also point to `accounts.id` through `account_id`.
62
+ - `external_activity_scans.account_id` points to `accounts.id`. It records which known local account the user-requested lookup or scan was scoped to.
63
+ - `external_activity_transactions.account_id` points to `accounts.id`, and `first_scan_id` / `last_scan_id` point to `external_activity_scans.scan_id`. `known_sender_account_id` points to `accounts.id` only when the sender is also a known local account. Non-known party account addresses are not stored; normalized detail JSON keeps account-owner and event-sender fields only when they match the known local account.
64
+ - `coin_metadata_cache` is account-independent and is keyed by coin type plus chain identifier.
65
+ - `local_settings` is independent local configuration and does not point to account or review rows.
66
+
67
+ The database does not create background transaction indexing tables. Complete external transaction history, raw GraphQL payloads, transaction bytes, signatures, BCS payloads, non-known party account addresses, and arbitrary transaction payloads are not product surfaces of this database.
68
+
69
+ Schema version 4 adds the `external_activity_scans.kind = 'function_scan'` provenance value. The startup migration rebuilds `external_activity_scans` with foreign keys temporarily disabled, copies rows unchanged, recreates indexes, runs `PRAGMA foreign_key_check`, and updates `user_version` only after the transaction succeeds. Existing rows are not backfilled from `account_scan` to `function_scan` because earlier scan rows do not store the function target needed for safe identification. Local-data backups containing `function_scan` provenance can be imported by version 4 runtimes; older runtimes reject them through their scan-kind validator rather than partially importing unsupported provenance.
70
+
71
+ Logical local data reset is the local settings page action that clears stored product state through the runtime without requiring manual database-file deletion. Replace-only import is the settings page import path that replaces local product state from a validated backup. Both logical local data reset and replace-only import clear `coin_metadata_cache`. Clearing active account context does not clear it because coin metadata is account-independent.
72
+
73
+ Non-terminal review session expiry is recorded lazily when the session is read or mutated after its TTL. There is no background expiry worker.
74
+
75
+ ## Boundaries
76
+
77
+ The active account is a read context only. It is not signing authorization, login, authentication for transactions, custody, permission for transactions, or proof of ownership. It stores at most one address per database file; setting a new active account replaces the previous one without revoking anything onchain.
78
+
79
+ NDJSON event logs remain optional audit/debug logs. They are not the product activity source of truth. User-facing activity summaries read from SQLite. Event log write failures do not fail product session transitions or SQLite evidence writes.
80
+
81
+ Session tokens, token hashes, and URL fragment tokens are never stored in SQLite. The activity-store evidence input types do not accept session token material, and review evidence JSON is checked with the same forbidden-field-name policy used for MCP output. Transaction bytes, signatures, serialized signing material, token-hash/session-token-like fields, seeds, mnemonics, and private-key-like field names are rejected before write. External proposal ingestion also rejects recognized Sui private-key strings, valid English BIP39 mnemonic phrases, obvious sensitive markers, and suspicious raw secret-like payloads before storing the sanitized requested intent. Generic asset metadata such as token symbols remains allowed.
82
+
83
+ The local settings table is not a secret store. It stores only allowlisted local preferences such as the Sui mainnet gRPC and GraphQL endpoints. It must not store database paths, tokens, credentials, private keys, mnemonics, seeds, or arbitrary API keys. Environment overrides such as `SUI_GRPC_URL` and `SUI_GRAPHQL_URL` can temporarily supersede stored endpoints without mutating the database.
84
+
85
+ Review intent capture follows one adapter convention: if an adapter wants the original requested intent materialized for activity queries, it must place that object at `ActionPlan.adapterData.requestedIntent`. The full `plan_json` remains the canonical action plan, and `intent_json` is only the query-friendly copy of that adapter-supplied intent.