불리언 하나가 상태 기계를 숨긴다
이 목록의 다섯 카드 — `rpc-view-not-consensus`, `receipt-is-not-settlement`, `bundler-paymaster-dependencies`, `private-rpc-visibility`, `walletconnect-session-authority` — 는 한 법칙을 다섯 번 본 것입니다. 하나의 UI 상태("연결됨", "전송됨", "성공", 초록 점)가 **서로 다른 당사자가 관찰하고 서로 다른 당사자가 결정하는 다중 소유자 상태 기계**를 뭉갭니다. 버그는 언제나 그 뭉갬이고, 해법은 언제나 **명시적 상태를 모델링하고 계층을 절대 섞지 않는 것**입니다.
이 페이지는 카드에 적힌 내용을 펼쳐 보여줄 뿐입니다 — 돌아가는 코드도, 열어볼 데모도 아직 없습니다. 무엇을 왜 만들려는지가 아래에 있습니다.
만드는 일이 아니라 **자기 UI 에 돌리는 설계 감사**입니다. 앱이 불리언으로 그리는 모든 상태(`isConnected`, `pending`, `confirmed`, `sent`, `paid`)를 나열하고 각각을 명시적 상태 기계로 밀어 넣습니다 — 그 불리언이 어떤 구별된 상태들을 뭉개는지, 각각의 **권위 있는 증인**이 누구인지, 무슨 이벤트가 그 사이를 옮기는지. 각 전이에 대해 그 계열에 맞는 불변식을 단언합니다 — **생애주기** 상태는 오직 *증거와 함께*(정규 receipt, 그다음 파이널리티) 파이널로 전진할 수 있고, **권한** 상태는 오직 *줄어들거나 다시 부여*될 뿐 조용히 넓어지면 안 됩니다. 그다음 거짓 양성(만료된 세션 위 초록 점, 파이널로 읽힌 receipt, 정산으로 읽힌 accepted op)과 거짓 음성(실패로 읽힌 보이지 않는 프라이빗 tx)을 찾습니다. 산출물은 표 하나입니다 — 상태 -> 숨긴 상태들 -> 각각의 소유자 -> 그것을 바꾸는 이벤트. 네 열을 못 채우는 것은 상태 기계를 두고 거짓말하는 불리언입니다.
기술 노트
각 항목이 실제로 무엇을 보여주고 어떻게 동작하는지 — 위 카드보다 자세한 기술 설명입니다.
목적: **공통 모양은 손실 있는 투영입니다 — 서로 다른 소유자를 가진 여러 상태를 비트 하나가 대신합니다.** 카드별로 읽으면 같은 뭉갬이 매번 나타납니다. `rpc-view-not-consensus`: 값은 노드 하나의 *관점*이지 체인의 *합의*가 아니다. `receipt-is-not-settlement`: *포함된* receipt 는 *파이널*이 아니다. `bundler-paymaster-dependencies`: *서비스가 접수함*은 *온체인 정산*이 아니다. `private-rpc-visibility`: *보이지 않음*은 *실패*가 아니다. `walletconnect-session-authority`: *연결됨*은 *이것에 대해 인가됨·최신임*이 아니다. 하나같이 **서로 다른 권위 소스를 가진 둘 이상의 구별된 상태**를 단어 하나로 그린 UI 입니다. **그 뭉갬은 양방향으로 위험하고, 그래서 자기 카드값을 합니다.** 거짓 양성은 스테일 상태를 살아남는 초록 점입니다 — 앱이 만료된 세션, 미포함 트랜잭션, 나중에 리오그되는 receipt 위에서 *확신을 갖고* 행동합니다. **UI 가 틀린 바로 그 순간 가장 확신하기 때문에** 최악의 버그입니다. 거짓 음성은 거울상입니다 — 퍼블릭 심장박동이 없는 프라이빗 트랜잭션이, 앱이 조용히 기대던 신호가 사라졌다는 이유로 실패로 읽힙니다. 어느 경우든 피해는 눈에 보이는 에러가 아니라 *확신에 찬 틀린 행동*이고, 이는 모니터링이 막아야 할 바로 그 실패 유형입니다. **해법은 두 계열로 갈리고, 그 둘에 이름을 붙이는 것이 이 카드의 목적입니다.** *생애주기 정직성*은 완료로 향하는 모든 것 — 읽기, 전송, 결제, 포함 — 을 덮습니다: 상태는 오직 *증거와 함께* 전진하고, 각 단계가 자기 증인을 지명하며(receipt, 그다음 파이널리티 — 제출 당사자 자신의 말이 아니라), '완료'는 파이널에만 씁니다. *권한 정직성*은 권력을 부여하는 모든 것 — 세션, 후원, 권한 — 을 덮습니다: 부여는 오직 *줄어들거나* 다시 요청될 뿐이고, 모든 변경 이벤트가 좁히거나 무효화하며, 조용히 넓어지면 안 됩니다. 둘 다 한 지시로 수렴합니다 — **각 상태의 소유자를 지명하고, 모든 전이를 관찰 가능한 이벤트로 만들고, 하나의 상태가 여럿을 대신하게 두지 마라.** 적은 초록 점이 아니라, *모델링되지 않은 상태 기계 위의* 초록 점입니다.
동작 방식: ### 한 법칙, 다섯 번 | 카드 | 그 불리언 | 숨긴 상태들 | 권위 있는 소유자 | | --- | --- | --- | --- | | `rpc-view-not-consensus` | "체인이 X 라고 함" | 노드 하나의 관점 대 합의 | 독립 노드들 | | `receipt-is-not-settlement` | "확정됨" | 포함 대 파이널 | 체인 파이널리티 | | `bundler-paymaster-dependencies` | "전송됨" | 서비스 접수 대 정산 | 번들러 / 페이마스터, 그다음 EntryPoint | | `private-rpc-visibility` | "대기 중" | 보이지 않음 대 실패 대 포함 | 무관한 퍼블릭 노드 | | `walletconnect-session-authority` | "연결됨" | 릴레이-켜짐 대 인가됨 대 최신 | 지갑의 세션 이벤트 | 세 번째 열을 위에서 아래로 읽으세요 — 모든 줄이 단어 하나를 입은 둘 이상의 상태입니다. ### 두 계열, 두 불변식 | 계열 | 덮는 것 | 불변식 | '완료'의 뜻 | | --- | --- | --- | --- | | **생애주기 정직성** | 읽기, 전송, 결제, 포함 | 오직 *증거와 함께* 전진; 각 단계가 증인을 지명 | 제출자의 말이 아니라 파이널 | | **권한 정직성** | 세션, 후원, 권한 | 오직 *줄어들거나* 재부여; 조용히 넓어지지 않음 | 명시적으로 재인가됨 | ### 뭉갬을 찾아내는 법 1. UI 가 단어 하나로 보여주는 상태를 가리킨다(연결됨, 전송됨, 확정됨). 2. 묻는다 — 그것이 몇 개의 *구별된* 상태를 대신하나? 하나보다 많으면 투영이다. 3. 각 상태에 대해 **권위 있는 증인**을 지명하고 — 제출 당사자 자신의 말은 증인으로 기각한다. 4. 상태 사이를 옮기는 **이벤트**를 지명하고, 그것이 오직 좁히거나 무효화(권한)하거나 증거와 함께 전진(생애주기)하는지 단언한다. 5. 상태·소유자·이벤트·불변식 네 가지를 못 채우면, 그 불리언은 거짓말을 하고 있다. ### 왜 각주가 아니라 카드인가 다섯 카드는 각자 자기 사례를 고칩니다. 이 카드는 **패턴**이라, 여섯 번째 사례를 버그를 배포하기 전에 알아볼 수 있게 합니다. 다음번에 어떤 설계가 다중 소유자 현실을 초록 점 하나로 줄일 때 — 크로스체인 '전달됨', 오라클 '해결됨', 에이전트 '인가됨' — 질문은 이미 적혀 있습니다: **그 점이 방금 어떤 상태들을 뭉갰고, 각각을 누가 소유하는가?**