마스터 계약 공식 이름 및 STEP3 활성화 대시보드 구현#57
Open
Jaymyong66 wants to merge 24 commits into
Open
Conversation
The new spec fixes two UX gaps at once: contracts need an official, durable name, and Step 3 needs to become an operational readiness dashboard instead of repeating participant confirmation. The design chooses on-chain storage for the master agreement name because backend persistence is not durable enough for the user's requirement. It also scopes Step 3 to a leader/operator snapshot dashboard, keeping time-series analytics out of the first implementation slice. Constraint: Master agreement names must survive backend loss and remain the official shared identifier Rejected: Backend-only metadata storage | name would disappear if backend state is lost Rejected: Existing-contract backfill | not required for this first rollout Confidence: high Scope-risk: moderate Reversibility: clean Directive: Treat the contract field as the single source of truth for master agreement names; do not reintroduce backend-owned naming Tested: Spec self-review for placeholders, ambiguity, and scope Not-tested: Implementation feasibility against exact Anchor account sizing and migration details
Persist a trimmed master agreement name at creation time and reject blank or overlong values before the account is initialized. The account space now reserves an explicit UTF-8 budget for the stored name. Constraint: Follow the task's TDD sequence with focused contract tests first Rejected: Accept raw input without trimming | would persist avoidable whitespace differences on-chain Confidence: high Scope-risk: narrow Directive: Keep create-time name validation aligned with MASTER_AGREEMENT_NAME_MAX_LEN if the limit changes Tested: cargo test create_master_agreement_test Tested: cargo test
Shared master agreement name normalization is reused for the new rename path, and the frontend IDL artifacts are synced to expose the instruction and account shape. Constraint: Keep scope limited to Task 2 instruction, tests, and regenerated IDL artifacts Rejected: Duplicating name normalization in the rename instruction | would fork a shared invariant Confidence: high Scope-risk: narrow Directive: Keep rename authorization limited to leader/operator unless the master agreement role model changes Tested: cargo test update_master_agreement_name_test; anchor build Not-tested: yarn test src/lib/__tests__/programEnv.test.ts (blocked by Yarn 1 vs packageManager yarn@4.1.0/Corepack requirement)
The regenerated JSON already included the rename instruction and added name fields, but the hand-maintained OpenParametric type block was still stale. Constraint: Keep the fix limited to the stale frontend TS IDL export Rejected: Regenerate or rewrite the full TS helper file | broader than the review item and would mix unrelated drift Confidence: high Scope-risk: narrow Directive: When JSON IDL is refreshed, update both helper interfaces and the exported OpenParametric type block together Tested: rg -n 'updateMasterAgreementName|"name": "name"' frontend/src/lib/idl/open_parametric.ts frontend/src/lib/idl/open_parametric.json; npx tsc --noEmit -p tsconfig.json Not-tested: Full frontend test suite
This follow-up closes the Task 2 review gaps by sharing name normalization between create and rename, extending rename-path tests to cover trimming and rejection cases, and making the frontend TS helper surface require the same name field the JSON IDL already defines. Constraint: Keep the fix limited to Task 2 follow-up review items without regenerating unrelated frontend artifacts Rejected: Leave normalization in create_master_agreement.rs | keeps a shared invariant hidden behind one instruction boundary Rejected: Update only the TS helper type without the typed hook consumer | would leave the frontend surface internally inconsistent Confidence: high Scope-risk: narrow Directive: If master agreement name rules change, update the shared helper and both create/rename tests together Tested: cargo test update_master_agreement_name_test; cargo test create_master_agreement_test; cargo test; npx tsc --noEmit -p tsconfig.json; rg -n 'export interface CreateMasterAgreementParams|name: string;|name: updateMasterAgreementName|name: name' frontend/src/lib/idl/open_parametric.ts frontend/src/lib/idl/open_parametric.json frontend/src/hooks/useCreateMasterAgreement.ts Not-tested: Interactive frontend create-master flow
Parse the on-chain master agreement name into backend responses and carry it through the frontend agreement summary/account mappers so downstream UI work can consume it. The backend test fixture now serializes the inserted string field, and related backend test constructors include placeholder names so the requested parser test command still compiles after the struct shape change. Constraint: The on-chain account layout inserts `name` immediately after `master_id`, so parser offsets had to shift without touching unrelated fields Constraint: Existing backend unit tests construct `MasterAgreementInfo` directly, so they needed the new field for the requested cargo test command to pass Rejected: Limit changes to the five requested files only | `cargo test program_accounts` failed to compile due to direct struct initializers in existing backend tests Confidence: high Scope-risk: narrow Directive: Keep backend/frontend field ordering aligned with the on-chain account layout when adding future master agreement fields Tested: `cd backend && cargo test program_accounts` Tested: Frontend TypeScript diagnostics clean for modified hooks/store and `src/store/__tests__/pure-functions.test.ts` via `npx tsc --noEmit --project frontend/tsconfig.json` Not-tested: `cd frontend && yarn test src/store/__tests__/pure-functions.test.ts` blocked by Yarn/Corepack workspace setup and lockfile state
Keep the workbench and dropdown aligned with the on-chain master agreement name so leaders and operators can create, review, and rename agreements without falling back to opaque identifiers. Constraint: The live STEP1 on-chain creation flow still batches raw instructions, so the create params had to stay inline while becoming typed and name-complete Rejected: Route creation through useCreateMasterAgreement | it only exposes an rpc path and cannot compose the existing multi-transaction setup flow Directive: Keep the on-chain create params and rename hook aligned with the IDL name field; do not drop the name/oracleFeed fields when the setup flow changes Confidence: high Scope-risk: narrow Tested: Dropdown rendering test via ./node_modules/.bin/vitest run src/components/layout/__tests__/MasterAgreementDropdown.test.tsx src/components/tabs/tab-contract/__tests__/MasterAgreementWorkbench.test.tsx; frontend typecheck via ./node_modules/.bin/tsc -b --pretty false Not-tested: Live wallet-backed create and rename transactions against a running backend/indexer
The workbench rename UI was gated on operator access, but the fetched agreement summaries never surfaced operator ownership, so selecting an operator-owned agreement could not set the store role correctly. Constraint: Operator access must continue to respect existing wallet-role precedence instead of overriding leader or participant ownership Rejected: Make the workbench bypass store role and inspect account ownership directly | it would hide the broken summary-selection path instead of fixing it Directive: Keep backend summary role detection and dropdown selection role sync in step when new roles are added Confidence: high Scope-risk: narrow Tested: ./node_modules/.bin/vitest run src/components/layout/__tests__/MasterAgreementDropdown.test.tsx src/hooks/__tests__/useMasterAgreements.test.ts; ./node_modules/.bin/tsc -b --pretty false Not-tested: Live backend response with a real operator-owned agreement in a connected browser session
The workbench could briefly fall back to stale or placeholder naming after create and rename because visible state depended on list/account refetch timing. This adds a narrow selected-name store surface so the active agreement keeps its official name immediately while reconciliation runs in the background. Constraint: The optimistic name must not be overwritten by the stale policy list during the same selection cycle Rejected: Wait for list/account refetch before updating the UI | it preserves the timing gap the review flagged Directive: Treat selectedMasterAgreementName as the immediate UI source for the active agreement only; refresh paths should reconcile it, not block on it Confidence: high Scope-risk: narrow Tested: ./node_modules/.bin/vitest run src/components/layout/__tests__/MasterAgreementDropdown.test.tsx src/components/tabs/tab-contract/__tests__/MasterAgreementWorkbench.test.tsx; ./node_modules/.bin/vitest run src/components/tabs/tab-contract/__tests__/MasterAgreementNameEditor.test.tsx; ./node_modules/.bin/tsc -b --pretty false Not-tested: Live wallet-backed create/rename with delayed backend index updates in a browser session
The review panel could still show a stale backend name even after the dropdown and editor had fresher local state, and the rename flow collapsed reconciliation into a single success state. This aligns the review surface with the optimistic selected name and makes refresh failures explicit while keeping the successful local update visible. Constraint: Keep the fix minimal and limited to precedence/toast semantics rather than reworking the refresh architecture Rejected: Wait for account refresh before showing any success state | it reintroduces the stale-name lag already fixed elsewhere in Task 4 Directive: When optimistic selected-name state exists for the active agreement, prefer it over lagging account data in read surfaces Confidence: high Scope-risk: narrow Tested: ./node_modules/.bin/vitest run src/components/tabs/tab-contract/__tests__/MasterAgreementNameEditor.test.tsx src/components/tabs/tab-contract/__tests__/MasterAgreementReviewPanel.test.tsx; ./node_modules/.bin/tsc -b --pretty false Not-tested: Live browser session with delayed account refresh after rename
The rename warning branch relied on rejected promises, but both master-agreement refresh hooks swallowed failures and resolved normally. This changes those refetch surfaces to return explicit booleans so the editor can distinguish successful reconciliation from local-only optimistic updates. Constraint: Preserve existing state updates and call patterns while adding a real success/failure signal Rejected: Infer failure from Promise.allSettled shapes in the editor | the hooks resolve on failure today, so that signal is false confidence Directive: Any UI that needs refresh-health semantics from these hooks should use their boolean return values rather than settlement shape Confidence: high Scope-risk: narrow Tested: ./node_modules/.bin/vitest run src/components/tabs/tab-contract/__tests__/MasterAgreementNameEditor.test.tsx src/components/tabs/tab-contract/__tests__/MasterAgreementReviewPanel.test.tsx; ./node_modules/.bin/tsc -b --pretty false Not-tested: Live browser session with backend fetch failures during rename reconciliation
Replace the duplicated STEP3 confirmation surface with a leader/operator snapshot that shows activation readiness, collateral coverage, and live money flow in one place. Constraint: Existing Yarn workspace resolution is broken in this worktree, so verification used direct local vitest/tsc binaries Rejected: Reuse ParticipantConfirm for STEP3 | it kept the activation surface as a duplicate of STEP2 instead of a snapshot dashboard Confidence: high Scope-risk: narrow Directive: Keep STEP3 focused on current activation readiness; do not expand it into historical analytics without a separate task Tested: ./node_modules/.bin/vitest run src/hooks/__tests__/useMasterAgreementSnapshot.test.ts src/components/tabs/tab-contract/__tests__/MasterAgreementWorkbench.test.tsx Tested: ./node_modules/.bin/tsc -b --pretty false Not-tested: yarn test in this worktree remains blocked by lockfile/workspace resolution
Use the selected or parsed master agreement name for the leader row in pool collateral status instead of always falling back to a generic label. Constraint: Keep the fix inside the existing pool-collateral label path without redesigning store-backed naming Rejected: Introduce a broader party-label abstraction | unnecessary scope for a single missing leader path Confidence: high Scope-risk: narrow Directive: Preserve the current fallback order for leader labels unless a dedicated leader-display source is added later Tested: ./node_modules/.bin/vitest run src/hooks/__tests__/useMasterAgreementSnapshot.test.ts src/components/tabs/tab-contract/__tests__/MasterAgreementWorkbench.test.tsx Tested: ./node_modules/.bin/tsc -b --pretty false
The activation review step became non-actionable after the dashboard swap, and unresolved policy fetches were rendering misleading zero-value money metrics. This shares the activation path across the participant and dashboard surfaces, exposes policy fetch state for the dashboard, and adds focused regressions for the step swap and loading/error handling. Constraint: Keep the Task 5 fix pass scoped to the existing activation and snapshot surfaces Rejected: Re-embed ParticipantConfirm inside the activation step | would duplicate the participant checklist UI instead of sharing the activation behavior Rejected: Null out the full snapshot during policy loading/errors | would hide valid collateral KPIs alongside the money snapshot regression Confidence: high Scope-risk: narrow Directive: Keep activation business logic shared between participant confirmation and activation dashboard surfaces Tested: vitest run src/hooks/__tests__/useMasterAgreementSnapshot.test.ts src/components/tabs/tab-contract/__tests__/MasterAgreementWorkbench.test.tsx src/components/tabs/tab-contract/__tests__/ParticipantConfirm.test.tsx src/components/tabs/tab-contract/__tests__/MasterActivationDashboard.test.tsx Tested: ./node_modules/.bin/tsc -b --pretty false (from frontend/) Tested: lsp_diagnostics_directory frontend
Simulation mode now derives its Step 3 dashboard from local agreement terms and pool state, while on-chain mode withholds collateral readiness until token balances are actually loaded. This preserves the dashboard handoff in simulation without routing users back to confirmation semantics, and it removes the synthetic zero-balance path that was producing false deficits during unresolved balance fetches. Constraint: Task 5 scope is limited to Step 3 dashboard correctness and directly related tests Rejected: Send simulation users back to the confirmation panel | breaks the Step 3 dashboard product intent Rejected: Keep zero-balance placeholders until fetch completes | shows false Action Needed and deficit states Confidence: high Scope-risk: narrow Directive: Do not treat missing collateral balances as authoritative funded data without an explicit resolved state Tested: vitest run src/components/tabs/tab-contract/__tests__ src/hooks/__tests__/useMasterAgreementSnapshot.test.ts; tsc --noEmit --pretty false -p tsconfig.json; lsp diagnostics on modified files; lsp_diagnostics_directory frontend
Task 5 still conflated policy fetch latency with readiness state, and token balance RPC failures could collapse into zero balances that rendered false blockers. This pass keeps readiness KPIs active while policy data loads, isolates policy-specific money-panel failures, and leaves collateral readiness unresolved when live balance reads fail. Constraint: Scope limited to the Task 5 Step 3 dashboard hook/component path and directly related regressions Rejected: Preserve a single loading/error channel for readiness and policies | it still hides ready collateral state behind policy fetch latency Rejected: Continue coercing token balance RPC failures to zero | it produces synthetic underfunded states from transport failures Confidence: high Scope-risk: narrow Directive: Do not fold policy loading/error back into readiness state without a separate unresolved UI path for missing collateral data Tested: ./node_modules/.bin/vitest run src/components/tabs/tab-contract/__tests__ src/hooks/__tests__/useMasterAgreementSnapshot.test.ts (from frontend) Tested: ./node_modules/.bin/tsc --noEmit --pretty false -p tsconfig.json (from frontend) Tested: lsp_diagnostics on modified frontend files; lsp_diagnostics_directory frontend Not-tested: Live Solana RPC integration behavior beyond mocked/unit coverage
Step 2 now stops at confirmation state and only advances into the Step 3 dashboard when approvals are complete. The dashboard also treats the live-balance handoff as loading so on-chain users do not briefly see an empty activation snapshot before balance reads begin. Constraint: Task 5 fix pass must preserve simulation and on-chain activation behavior once Step 3 loads Rejected: Leave activation wired in ParticipantConfirm | bypasses Step 3 ownership and guide target Confidence: high Scope-risk: narrow Directive: Keep \ attached to MasterActivationDashboard unless Step ownership changes again Tested: frontend vitest run src/components/tabs/tab-contract/__tests__ src/hooks/__tests__/useMasterAgreementSnapshot.test.ts Tested: frontend tsc -b --pretty false Tested: frontend lsp_diagnostics_directory + modified-file diagnostics Not-tested: Manual browser walkthrough
The guided tour still targeted the old single-step activation path, and the new dashboard CTA could be clicked before the on-chain account fetch finished. This patch adds a dedicated tour stop for the Step 2 transition, shifts the downstream step wiring by one slot, and disables on-chain activation until the required account data is present. Constraint: Keep scope limited to Task 5 activation flow guidance and readiness checks Rejected: Reuse snapshot data for activation wallets | snapshot path does not expose the full account payload needed for on-chain activation Confidence: high Scope-risk: narrow Directive: If the activation flow changes again, update both GUIDE_STEPS sequencing and GuideTour auto-advance/manual-step mappings together Tested: frontend vitest run src/components/tabs/tab-contract/__tests__ src/hooks/__tests__/useMasterAgreementSnapshot.test.ts Tested: frontend tsc --noEmit --pretty false -p tsconfig.json Tested: lsp_diagnostics_directory frontend Not-tested: Interactive browser walkthrough of the guide overlay
Task 5's activation path was fetching the same master-agreement account through the dashboard, snapshot, and collateral hooks. This change centralizes the account fetch in the dashboard, threads the resolved master state into the dependent hooks, and gives the Step 2 transition button its own label so it is distinct from the real Step 3 activation CTA. Constraint: Keep the fix local to the Task 5 activation dashboard path and directly related tests/i18n Rejected: Introduce a broader shared context/provider for master agreement data | too broad for a fix pass Rejected: Leave snapshot and collateral hooks to fetch the same PDA independently | preserves duplicate backend fetch and SSE chains Confidence: high Scope-risk: narrow Tested: ./node_modules/.bin/vitest run src/components/tabs/tab-contract/__tests__ src/hooks/__tests__/useMasterAgreementSnapshot.test.ts Tested: ./node_modules/.bin/tsc -b --pretty false Tested: lsp_diagnostics_directory frontend and per-file diagnostics on modified files
The workbench was still treating confirmation readiness as equivalent to a user-entered activation transition, which hid the transition CTA and let the guide advance on the wrong signal. Constraint: Keep scope limited to the Task 5 Step 3 transition and directly related regression tests Rejected: Broader workbench step-state refactor | unnecessary for the verified regression surface Directive: Do not auto-select the activation dashboard from readiness state alone; only activation or an explicit user transition should cross that boundary Confidence: high Scope-risk: narrow Tested: vitest run src/components/tabs/tab-contract/__tests__ src/hooks/__tests__/useMasterAgreementSnapshot.test.ts; tsc -b --pretty false; lsp_diagnostics_directory frontend
The UI was trusting the derived store role even though the program only accepts the wallet stored in master.operator. This narrows on-chain actionability to the loaded operator key while leaving simulation behavior role-based for local previews. Constraint: On-chain activation authority is defined by master.operator, not the frontend role mirror Rejected: Keep leader/operator role gating and handle Unauthorized after click | preserves the dead-end CTA Confidence: high Scope-risk: narrow Directive: Do not widen on-chain activation eligibility without comparing against the loaded operator account Tested: vitest run src/hooks/__tests__/useMasterAgreementActivation.test.ts; vitest run src/components/tabs/tab-contract/__tests__/MasterActivationDashboard.test.tsx; ./node_modules/.bin/tsc -b --pretty false (frontend)
Selected agreement names were staying pinned to the optimistic store value long after the backend/account refresh had published a newer name. This adds a narrow sync path that keeps the optimistic label until the authoritative value actually changes, then updates the selected name without redesigning the store. Constraint: Keep optimistic rename feedback immediate without a broader store rewrite Rejected: Always prefer fetched names over selectedMasterAgreementName | would erase the optimistic rename before refresh completes Confidence: high Scope-risk: narrow Directive: Preserve the optimistic name only until the authoritative source changes; do not make selectedMasterAgreementName permanently dominant again Tested: vitest run src/components/layout/__tests__/MasterAgreementDropdown.test.tsx src/components/tabs/tab-contract/__tests__/MasterAgreementNameEditor.test.tsx src/components/tabs/tab-contract/__tests__/MasterAgreementReviewPanel.test.tsx; ./node_modules/.bin/tsc -b --pretty false (frontend)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
요약
이 PR은
Master Agreement의 공식 이름 기능과STEP3 풀 활성화대시보드 전환을 함께 구현합니다.핵심 변경:
MasterAgreement.name을 온체인에 저장leader/operator가 마스터 계약 이름을 수정할 수 있는 rename instruction 추가주요 변경 사항
1. 컨트랙트 / 온체인
MasterAgreement계정에name: String필드 추가update_master_agreement_nameinstruction 추가2. 백엔드
MasterAgreement파서가master_id뒤의name을 읽도록 변경3. 프론트 - 이름 UX
name을 보내도록 수정계약명 · 상태 · 역할 · 종료일형식으로 표시4. 프론트 - STEP3 대시보드
MasterActivationDashboard로 전환사용 방법
새 마스터 계약 생성
STEP1 기본 설정에서 공식 이름을 입력합니다.이름 수정
leader또는operator권한으로 이름 수정 UI를 엽니다.STEP3 활성화
활성화 대시보드로 이동버튼으로 STEP3로 이동합니다.주의사항
1. 기존 legacy Master Agreement 호환성
이번 구현은 새로 생성되는 계약부터 공식 이름을 저장하지만, 운영 중인 기존 계약이 즉시 사라지지 않도록 백엔드에 old/new layout fallback parser를 추가했습니다.
즉:
name을 정상적으로 읽습니다.name=""으로 fallback 파싱합니다.제약:
2. activation 권한
master.operator기준으로 activation CTA를 gating 하도록 맞췄습니다.leader != operator인 계약에서는 leader가 CTA를 눌렀다가 런타임에서 거절당하는 dead-end를 피하도록 정리했습니다.3. optimistic 이름 표시
즉 일시적 backend refresh 지연이 있어도 이름이 바로 사라지지 않도록 처리했습니다.
4. STEP3 데이터 로딩
0.00 USDC, 가짜 deficit, 가짜 blocker를 보여주지 않도록 수정했습니다.테스트 / 검증
Contract
cargo test133 passed / 0 failedBackend
cargo test31 passed / 0 failed / 4 ignoredFrontend
환경상
yarnworkspace/lockfile 경로가 불안정해서, repo-local binary 기준으로 검증했습니다../node_modules/.bin/vitest run src/components/tabs/tab-contract/__tests__ src/hooks/__tests__/useMasterAgreementSnapshot.test.ts7 files / 29 tests passed./node_modules/.bin/tsc -b --pretty falsegit diff --check리뷰 포인트
name추가가 legacy 계정과 공존해야 하는지leader/operator권한 모델이 현재 제품 요구와 맞는지