Skip to content

feat(exo-1f9): members share accounts of their own with the room; releases ship every platform - #346

Merged
corpetty merged 5 commits into
mainfrom
feat/member-accounts
Oct 24, 2026
Merged

corpetty merged 5 commits into
mainfrom
feat/member-accounts

Conversation

@corpetty

Copy link
Copy Markdown
Owner

Summary

  • Members' own accounts (exo-1f9). A member shares an account their muster keystore holds with the room (a LEZ public account first), so anyone in the room can use it where an account of theirs is needed.
    • The proof. member/<who>/account/<address> is author-signed and carries the account key's BIP-340 signature over hash-input muster.member-account.v1 {room, member, chain, kind, key}. So it counts only for that member, only in this room, and only for the first member who proved that key.
    • Stopping. /retract takes an account back.
    • Labels. The keystore label is never sent. The owner's client derives the candidates (crypto/account_labels.nim: lez-member/0, the paying account; lez-account/<n>, fresh ones).
    • Hosted: coordinate_disclose_my_account, coordinate_member_accounts, coordinate_retract_my_account.
  • LEZ multisig setup with them.
    • lez_msig_open {accounts: {identity: key}} picks, for any member, one of the accounts they shared as their approval key. It counts as their join, so their client derives no fresh key.
    • The driver, settlement and proposing find a member's key through myMsigLabel: the derived key or a shared account, whichever the config holds.
    • An account the member did not share is refused at open.
    • The fresh per-multisig key stays the default, because the public posture puts keys on chain and one account used in several multisigs links them. The UI says so.
  • UI. The room's accounts panel gets "Members' own accounts" (Share a new LEZ account, Share my paying account, Stop sharing). The LEZ multisig form gets each member's approval key: a new key, or one of the accounts they shared. Looking at it on a display found two layout problems, both fixed: a row that widened the whole narrow panel, and a Create button placed before the choices it depends on.
  • Releases ship every platform (exo-04f). catalog-release.sh takes muster_module and muster_ui from the lgx variants run that built HEAD (linux-amd64, linux-arm64, darwin-arm64). When no run built HEAD, it dispatches one and waits. --here builds for this host only, as every release so far did.

Tests

  • module/tests/run-suite.sh: 278/278.
  • member_accounts_test 5/5:
    • disclosure and proof;
    • another member's key, another room's proof, and an unauthored disclosure are all refused;
    • retract;
    • a multisig set up with Bob's account: his join, the config's key, his approval counted;
    • his proposal.
  • lez_msig_live_e2e §7 on a local LEZ v0.3 zone: the program paid on Bob's approval and on his proposal, both signed with his shared account.
  • On a display (two runners, Xvfb): A shared an account, picked it as its own approval key, and created a 2-of-2. The program's config holds that key.
  • scripts/ui-parity.sh 12/12; scripts/ui-lint.sh 0 new; check-action-corpus (new room/share-my-account).

🤖 Generated with Claude Code

… a LEZ multisig can be set up with it

A member puts an account their muster keystore holds in front of the room (a LEZ public
account first), so anyone in the room can use it where an account of theirs is needed.

- coordination/member_accounts.nim: member/<who>/account/<address>, author-signed, with
  the account key's BIP-340 proof over hash-input "muster.member-account.v1" {room, member,
  chain, kind, key}. It counts only for the member it proves, only in this room, and only
  for the first member who proved that key; /retract takes it back. The keystore label is
  never sent: crypto/account_labels.nim derives the candidates (lez-member/0, the paying
  account; lez-account/<n>, fresh ones).
- lez-msig: lez_msig_open {accounts: {identity: key}} picks, for a member, an account they
  shared, as their approval key. It counts as their join, so their client derives no fresh
  key. The driver, settlement and proposing find the member's key through myMsigLabel (the
  derived key or a shared account, whichever the config holds). An account the member did
  not share is refused at open.
- hosted: coordinate_disclose_my_account / coordinate_member_accounts /
  coordinate_retract_my_account.
- UI: "Accounts members shared" in the room's accounts panel (Share a new LEZ account,
  Share my paying account, Stop sharing), and, in the LEZ multisig form, each member's
  approval key: a new one, or one of the accounts they shared.

Tested-Behavior: member_accounts_test 5/5 (disclosure and proof; another member's key, another room's proof, an unauthored one all refused; retract; a multisig set up with Bob's account: his join, the config's key, his approval counted; his proposal); lez_msig_live_e2e §7 on a local LEZ v0.3 zone: the program paid on Bob's approval signed with his shared account; probe_return_marshalling_host; ui-lint 0 new; check-action-corpus
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Session-Id: 82cf96d0-9403-5a71-95d3-2ef04ee3e51c
… shared accounts (exo-1f9)

catalog-release.sh takes muster_module and muster_ui from the lgx variants run that built
HEAD (linux-amd64, linux-arm64, darwin-arm64, merged into one .lgx per package). When no run
built HEAD, it dispatches the workflow on HEAD's pushed branch and waits for it. --here builds
on this host for its platform only, as every release before this one did. lez_msig_module is
still built here, for linux-amd64. RELEASING.md and CLAUDE.md follow, and docs/design/lez-msig.md
§8 describes approval keys from accounts members shared.

TDD-Exempt: release script and docs; exercised by the next release (the run lookup, the dispatch-and-wait, --from-run's existing checks)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Session-Id: 82cf96d0-9403-5a71-95d3-2ef04ee3e51c
Seen on a display: the name field and the two share buttons sat in one row whose minimum
width exceeded the room details panel. The ColumnLayout then widened every filled child to
match, so the caption and "Add an account" were clipped at the panel's edge. The name field
now has a row of its own, the buttons wrap in a Flow, and an account's line wraps rather than
setting the row's width. The section is renamed "Members' own accounts", so it is not read
as the room's shared accounts above it.

Tested-Behavior: ui-lint 0 new; looked at again on a display after the rebuild
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Session-Id: 82cf96d0-9403-5a71-95d3-2ef04ee3e51c
…ount proposes on chain

Seen on a display: A shared "savings", picked it as its own approval key, and created a 2-of-2;
the program's config holds that key. Fixed what looking showed:
- the form said every member takes part "with a new key", which a picked account makes
  untrue; now "unless you pick an account they shared below";
- Create sat beside the threshold fields, truncated in the narrow panel, above the key
  pickers it depends on. It now has its own row, after the pickers;
- the name field kept its text after sharing.
lez_msig_live_e2e §7 now also has Bob propose from his shared account: the program checks the
proposer's signature with that key, and pays.

Tested-Behavior: lez_msig_live_e2e 7/7 on a local LEZ v0.3 zone (§7: paid on Bob's approval and on his proposal, both signed with his shared account); ui-lint 0 new
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Session-Id: 82cf96d0-9403-5a71-95d3-2ef04ee3e51c
TDD-Exempt: issue tracker events only
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Session-Id: 82cf96d0-9403-5a71-95d3-2ef04ee3e51c
@corpetty
corpetty merged commit 33a8309 into main Oct 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant