feat(siwe): act as a Safe — switcher, persistent banner, subject-aware profile - #103
Open
douglance wants to merge 3 commits into
Open
feat(siwe): act as a Safe — switcher, persistent banner, subject-aware profile#103douglance wants to merge 3 commits into
douglance wants to merge 3 commits into
Conversation
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
douglance
force-pushed
the
siwe/act-as-ui
branch
from
August 17, 2026 17:28
a140cba to
590b4e1
Compare
douglance
force-pushed
the
siwe/act-as-ui
branch
from
August 19, 2026 21:01
590b4e1 to
3e955de
Compare
douglance
force-pushed
the
siwe/act-as-ui
branch
from
August 20, 2026 16:45
3e955de to
08d4031
Compare
fionnachan
force-pushed
the
siwe/act-as-ui
branch
from
August 20, 2026 16:55
08d4031 to
ef06755
Compare
…the full mount The SIWE mount exposes 24 routes; the client wrapped 6. Add the remaining 18 (session, safes, act-as, drafts, elections, candidate profiles). Every call now goes through one send() helper, including the five that previously hand-rolled fetch + parse — one convention in the file rather than two. That also fixes logout(), which fire-and-forgot its response, so a failed sign-out looked successful while the server kept the session alive. Query keys: the indexer resolves every owned read/write against effectiveSubject = actingAs ?? address, so act-as is a server-side mode and the same URL means a different subject once it flips. Caching across that boundary can put one entity's data into a form whose Save writes it to another. Every subject-scoped key therefore nests under one shared SUBJECT_SCOPE prefix carrying the effective address, so eviction on a subject switch is a single removeQueries() and a newly added subject-scoped query is covered the moment it is written — no parallel list to keep in sync. keys.test.ts pins that invariant. Signer-scoped keys are kept deliberately separate: /api/auth/safes resolves against session.address, not the effective subject, so acting as a Safe must not move it. MeResponse.safes was typed unknown[] but is a bare string[]; the enriched KnownSafe[] only comes from /api/auth/safes. The draft governor type is DraftGovernorType rather than GovernorType because config/governors.ts already owns that name with different values.
douglance
force-pushed
the
siwe/act-as-ui
branch
from
August 24, 2026 16:26
ef06755 to
b759bea
Compare
They are regenerated by the setup project on every run and were already gitignored; the ignore rule never applied because they were tracked.
…e profile Adds the UI for GET /api/auth/safes and POST/DELETE /api/auth/act-as. The Safe list is a recall table: the indexer only remembers a Safe after a successful act-as, so it is empty for every new user. A picker alone would be a dead end, which is why the by-address dialog is always offered rather than hidden as a power-user path. It stays open on failure so the indexer's reason (404 not a Safe / 403 not an owner) sits next to the address that caused it. useSafes keys on session.address, not the connected wallet. Those diverge — sign in as A, switch wallet to B without signing out — and the response belongs to whoever the session says you are, so keying on the connected address would file A's Safes under B. Leaving act-as drops every subject-scoped query in one removeQueries(SUBJECT_SCOPE), which also covers subject-scoped queries added later. ActingAsBanner is deliberately not dismissible. Act-as lives on the session row and the cookie is 7 days on a sliding window, so the mode outlives reloads, tab closes, and restarts; without a permanent marker a user can return days later and quietly edit the Safe's profile believing it is their own. ProfileEditor names the subject it will write for the same reason.
douglance
force-pushed
the
siwe/act-as-ui
branch
from
August 27, 2026 18:08
b759bea to
513cc9f
Compare
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.
Stacked on #102. Second of four.
Adds the UI for
GET /api/auth/safesandPOST/DELETE /api/auth/act-as.Two design points that drove the shape
The Safe list is a recall table, not a discovery one. The indexer only remembers a Safe after a successful act-as, so
GET /api/auth/safesis empty for every new user. A picker alone would be a dead end with no way in — which is why "Act as a Safe by address…" is always offered rather than tucked away as a power-user path. The dialog deliberately stays open on failure so the indexer's reason (404 not a Safe / 403 not an owner) sits next to the address that caused it.ActingAsBanneris deliberately not dismissible. Act-as is stored server-side on the session row, and the cookie is 7 days on a sliding window — so the mode outlives reloads, tab closes, and restarts. Without a permanent marker, a user can come back days later and quietly edit the Safe's profile believing it is their own.ProfileEditornow names the subject it will write for the same reason.Review focus
The cache-eviction path in
hooks/use-act-as.ts. Keys already embed the effective address (#102), so a stale entry cannot be read as the new subject's; the extraremoveQuerieson switch stops the old subject's data lingering and flashing back when toggling to and fro.Verification
pnpm test— 1225 unit tests pass. Behaviour is covered end to end by the spec in the fourth PR of this stack (5 tests, including 404safe_not_foundand 403not_an_owneragainst a real Safe on the local testnode).