Commit graph

51 commits

Author SHA1 Message Date
veg
3fe5615ffe fix: a transcript rescue never replaces an earlier one
The destination name has one-second granularity and mv overwrites.
Closing, re-hosting and closing the same party name within a second
would lose the first transcript while reporting success. Fall back to
a PID-suffixed name when the destination already exists.
2026-09-21 15:03:34 +00:00
veg
471ee5875c fix: log broadcast says 'this party' again
Routing log_notify through .party-notify had turned the announcement
into 'started logging the party'. The helper takes an optional object
phrase, defaulting to 'the party' for the join/leave hooks, and
log_notify passes 'this party'. Both wordings are now pinned by stub
tests, which had no coverage of the broadcast text before.
2026-09-21 11:37:30 +00:00
veg
733633bd65 style: no em-dash in post-install.sh comments 2026-09-21 09:48:23 +00:00
veg
81bf13bb8f docs: roadmap keeps the standing matrix gap, not the last status
The dated account of the 2026-07-11 pass is history, and fbe8317
already records it.
2026-09-21 09:48:23 +00:00
veg
e9455180eb docs: man page lists .log-panes, DragonFly, drops a dangling credit
FILES omitted the pane list that log --stop relies on and credited
only close with the transcript rescue that clean also performs. The
SECURITY platform list lacked DragonFly. AUTHORS pointed at additional
credits in the script header, which holds none.
2026-09-21 09:48:23 +00:00
veg
34a79276ac docs: README points at --help and the man page for reference
The subcommand table was a third copy of usage() and party.1 and had
drifted from both (no --group, no rw/ro aliases, no --version).
2026-09-21 09:48:23 +00:00
veg
fa36c29584 docs: README quick start leads with hosting, not groupadd
Since host time auto-selects a shared group, most boxes need no
setup. The dedicated 'party' group moves below as the fallback it is.
2026-09-21 09:48:23 +00:00
veg
552b33d25a docs: README caveat list no longer counts itself
It announced three caveats and listed four.
2026-09-21 09:48:23 +00:00
veg
521777215d style: no em-dash in test comments 2026-09-21 09:48:23 +00:00
veg
120fed8cb4 docs: prune history and orphans from party's comments
Rationale stays; what goes is narration of past revisions (git log
has it), a 'Library mode' section heading with no code under it, a
helper description left above cmd_role after the helper was folded in,
a claim that cmd_close trusts the roster's SOCKET (it never reads it),
and pointers to a README section that is named Security. The FS perms
platform list gains DragonFly.
2026-09-21 09:48:02 +00:00
veg
8661d2968e refactor: host pre-check probes its own socket path
The already-running check read the roster back only to learn the
socket path cmd_host had computed a few lines earlier. The roster's
presence still gates the probe: a leftover dir without one keeps
falling through to the mkdir lock and its 'party clean' hint.
2026-09-21 09:47:27 +00:00
veg
d51656c9e4 refactor: drop dead weight (unused param, duplicate checks, dead code)
- tmux_party_setup_server took an unused name parameter; drop it.
- validate_party_name ran two separate case blocks with a length
  check between them; merge into one case now that the length check
  (which an empty name always passes) runs first.
- roster_read now applies the RR_GROUP fallback to TMUX_PARTY_GROUP
  once, so cmd_join, cmd_invite, and cmd_list no longer each repeat
  ${RR_GROUP:-$TMUX_PARTY_GROUP}.
- socket_path had no caller in party; remove it and its test.
2026-09-21 09:46:05 +00:00
veg
bdcad47147 refactor: drop eval from pick_live_party
Select the chosen positional argument with shift + "$1" instead of
building a $pick-indexed variable reference through eval.
2026-09-21 09:42:19 +00:00
veg
c28101e2e8 refactor: direct roster lookups in cmd_role and cmd_who
cmd_role's TMUX-socket match and cmd_who's --socket branch each walked
every roster via roster_list to find the one record they already knew
the path to. Read that record directly instead. roster_read still
validates the dir basename and ownership, so a non-party socket falls
through to cmd_role's existing fallback loop.
2026-09-21 09:42:03 +00:00
veg
fb92ea1ae7 refactor: extract guest session helpers
The __party_guest_$user session name was spelled out in cmd_join,
cmd_leave, cmd_status, cmd_role, and _disconnect_user. Add
guest_session_name to print it consistently. Add ensure_guest_session
for the has-session/new-session snippet duplicated in cmd_join and
cmd_role. Add caller_present_on for the client-or-guest-session OR
duplicated in cmd_leave and cmd_status.
2026-09-21 09:41:31 +00:00
veg
9544f605a6 refactor: extract resolve_joinable_party from join and knock
cmd_join and cmd_knock both resolved an optional name argument to a
live party via find_party_by_name/pick_live_party with identical error
handling. Share it in one helper.
2026-09-21 09:37:42 +00:00
veg
c789f4985b refactor: log_notify delegates to the generated .party-notify script
log_notify re-implemented the client-fanout loop that .party-notify
(written at host time) already provides. Call that script instead.
Wording changes from "logging this party" to "logging the party" to
match the script's "$user $verb the party" template.
2026-09-21 09:37:13 +00:00
veg
45368232b4 refactor: extract rescue_transcript helper from close and clean
cmd_close and cmd_clean each rescued <party dir>/log to
$HOME/party-<name>-<timestamp>.log before removing the dir, with
close's drain poll as the only difference. Share the mechanism in one
helper and keep each caller's own messages and control flow.
2026-09-21 09:36:49 +00:00
veg
9980d2918a refactor: reuse user_in_group helper for membership checks
cmd_join, cmd_invite, and cmd_list each inlined the id -nG | tr | grep
pipeline instead of calling the existing user_in_group helper. cmd_list
also re-forked id once per party in its loop; now the caller's groups
are captured once before the loop. Also fold user_in_party_group (one
caller) into require_caller_in_group and drop the wrapper.
2026-09-21 09:35:39 +00:00
veg
698fff91ee fix: consistent usage errors for list, leave, status, who, log
list ignored --help and listed parties; leave and status ignored stray
arguments; who silently kept the last of several positionals; log took
a positional name that neither its usage nor the man page documents.
All now follow the parser convention of the other subcommands: help on
-h, exit 2 on an unknown flag or unexpected argument.
2026-09-21 09:33:36 +00:00
veg
9b85485ee8 fix: party list tags the group only when parties differ on it
The tag was shown whenever a party's group differed from
TMUX_PARTY_GROUP, which falls back to 'party' when unset. Since host
time auto-selects the group, a box gating on 'staff' tagged every
line. Compare the visible parties with each other instead.
2026-09-21 09:32:48 +00:00
veg
851cef6941 fix: a signal during party host rolls back and stops
The rollback trap was armed on EXIT INT TERM HUP with a body that did
not exit. After a signal the shell ran the cleanup, then resumed
cmd_host and kept configuring the party dir it had just removed.
Keep the cleanup on EXIT and make the signal traps exit with the
conventional 128+n status.
2026-09-21 09:32:01 +00:00
veg
6c48777553 fix: party log --stop closes only the pipes it opened
Start already skipped panes the host had piped for other purposes,
but --stop swept every pane, killing pipes party log never owned.
Record the pane ids we pipe in .log-panes inside the per-party dir
and close exactly those on --stop; the file dies with the dir.
2026-07-11 16:54:57 +00:00
veg
fbe8317fee docs: note matrix verification of knock, log, clean 2026-07-11 13:36:20 +00:00
veg
df9c1cb0dc fix: polish transcript rescue and doc drift from review
Guard HOME for set -u in the rescue paths, surface a failed rescue mv
instead of silently dropping the transcript, and never delete the
party dir after a failed save in either close or clean (close now
refuses to delete and exits nonzero on a failed rescue too, matching
clean, since a message promising the transcript survived followed by
rm -rf was a false assurance). Also stop log --stop from announcing a
stop that never started, and sync README's knock/log/write(1) wording
with the actual behavior.
2026-07-11 13:21:20 +00:00
veg
8d10e62779 feat: party clean rescues an orphaned transcript before deleting
A server crash mid-logged-party is the one case close's rescue can
never have run, and host's EEXIST message funnels the host straight
into clean. Deleting the night's log there is exactly the accident
class the close-time rescue exists for, so clean applies the same
rescue: no quiescence poll needed, the liveness gate just proved the
writers are gone.
2026-07-11 13:13:05 +00:00
veg
f946c7e876 test: pin the no-candidate host test against real group membership
The remediation-message test relied on the runner not being in group
'party'; on boxes where the runner is (the deployment hosts), host
succeeded and the test failed. Route the child's id(1) through the
suite's stub so the caller is deterministically in no candidate group.
2026-07-11 13:11:49 +00:00
veg
aea7ef58b6 feat: party log records a group-readable transcript
tmux pipe-pane on every pane of the party session, appending into
<party dir>/log (0640, party group) so any attendee can grab a copy.
Start and stop are announced to everyone attached; close rescues a
non-empty transcript to the host's home before removing the dir.
Panes opened later are picked up by re-running party log (a
pane_pipe check keeps already-piped panes single-piped, since tmux's
pipe-pane -o toggles an existing pipe closed rather than skipping it).
Raw output, escapes included. Close polls the transcript for size
stability before rescuing it, since a cross-filesystem mv is
copy+unlink and could otherwise drop bytes still draining from the
pipe-pane writers.
2026-07-11 12:59:41 +00:00
veg
a011e4b03c feat: party clean removes the caller's own crash leftovers
Turns the manual rm -rf recovery from host's EEXIST message into a
verb, behind the same gates cmd_close uses: own-basename glob, no
symlinks, ownership check, and a dead socket. Live parties are skipped
with a pointer to party close.
2026-07-11 12:32:39 +00:00
veg
6799a57405 feat: party knock asks an invite-only party's host for an invite
party list already shows invite-only parties; knock closes the loop.
The knocker can't run any tmux command against the server, so the
channel is write(1), the same one invite uses toward guests, except
here delivery failure is surfaced: the ping is the whole feature.
2026-07-11 12:24:31 +00:00
veg
7770289d85 feat: auto-select the gating group; 'party' becomes the fallback
Bare 'party host' now walks staff, users, wheel, party and gates on
the first group the caller belongs to, announcing the pick. Boxes
where people already share a system group need no setup; the curated
'party' group remains the fallback and the explicit --group /
TMUX_PARTY_GROUP paths are unchanged. Caller membership is the only
probe (id -nG, portable everywhere); whether a guest is a member stays
an invite-time warning, where it can actually be answered.
2026-07-11 12:20:35 +00:00
veg
22606ea55d docs: drop shipped liveness consolidation from roadmap 2026-07-11 12:07:23 +00:00
veg
6b94255245 refactor: fold is_party_alive into party_conn_state
One liveness primitive instead of two. The PID argument was a vestige
(format-checked, never probed, since the kill -0 removal); dropping it
means a roster with a garbage SERVER_PID can no longer mask a live
socket in host/moderation/role resolution.
2026-07-11 12:07:13 +00:00
veg
be3fb049d2 style: reword em-dashes; put colons inside bold run-in labels
Punctuation sweep across README, ROADMAP, and the script's comments:
em-dashes become colons, commas, or parentheses; bold list labels take
the colon inside the bold with lowercase text after. Comments only in
the script, no code changes.
2026-07-11 11:57:04 +00:00
veg
ff92d812ad docs: state the accidents-not-adversaries threat model; add ROADMAP
The gates in front of destructive operations exist to stop mistakes
(stale rosters, typos, racing hosts); stopping a malicious group
member is a side effect, not the design goal. Written into README
§Security and the man page so future checks are judged by that bar.
ROADMAP.md captures the direction: social features (knock, log,
clean) over further hardening, plus the explicit resist list.
2026-07-04 14:41:43 +00:00
veg
938491df1e fix: classify unauthorized by stderr presence, not denial wording
Review flagged the 'access not allowed' substring:
if tmux's denial text drifts while keeping exit 0, unauthorized
connections would classify as ok and the false-joined status/leave
misreporting would silently return. A clean authorized list-clients
writes nothing to stderr (verified 3.3a/3.5a/3.6-SunOS, incl. invited
read-only clients), so rc 0 plus any stderr output now classifies as
unauthorized: no message text consulted. Drift in any direction
degrades to a hidden party, never to a false ok.
2026-07-04 14:03:53 +00:00
veg
b44a3b705f fix: harden party_self_path; pin (U,R) ACL format; widen breakage comments 2026-07-04 10:42:58 +00:00
veg
2dc9285433 docs: repair README and deploy.sh drift
README: tmux requirement wording, invite-only list marker, name
charset, --party on moderation rows, PARTY_SOCKET_DIR whitespace note,
read-only join fallback. deploy.sh: drop phantom tests/run-remote.sh
include (file lives under legacy/ only) and fix the ship-list comment.
SERVERS.md and HISTORY.md were refreshed too but stay local-only per
.git/info/exclude ("Local docs — never published").
2026-07-04 10:33:14 +00:00
veg
44b97e9d6b docs: sync usage() and man page with actual CLI surface 2026-07-04 10:26:44 +00:00
veg
587a462e3c fix: read-only invitees auto-join passive
tmux refuses new-session from read-only clients ('client is
read-only'), so an active join for an -r invitee died under set -eu
with a raw tmux error. Detect the R flag on the caller's ACL line in
the existing preflight and fall back to the mirrored view.
2026-07-04 10:00:01 +00:00
veg
f3209e39d1 fix: classify unauthorized tmux connections; stop misreporting membership
tmux answers non-allowlisted users with 'access not allowed' on stderr
and exit 0 for every command (verified 3.3a/3.5a, two users), so
has-session reports any target as existing. party status claimed
uninvited group members were joined, party leave silently 'succeeded',
and party list printed bogus '0 attendee(s)' rows. New party_conn_state
(ok/unauthorized/dead) classifies by message content; list now shows
'invite-only (ask <host>)'.
2026-07-04 09:55:47 +00:00
veg
6cac86bb15 fix: guard non-tty join picker; refuse whitespace PARTY_SOCKET_DIR 2026-07-04 09:50:35 +00:00
veg
0d1b5ef796 fix: exec join attach with quoted args, not an unquoted string 2026-07-04 09:47:04 +00:00
veg
e174226651 fix: quote embedded paths in status-right widget 2026-07-04 09:44:32 +00:00
veg
2ef4eb49ce fix: pin absolute script path in status-right widget
The #() body runs with the tmux server's PATH; a bare 'party' silently
broke the widget for uninstalled or non-standard-prefix hosts.
2026-07-04 09:39:45 +00:00
veg
7d95850461 fix: .party-notify uses PARTY_TMUX, not bare tmux from PATH 2026-07-04 09:25:27 +00:00
veg
fc366f48fa fix: let voice/mute/kick/detach take --party
A host of two or more parties was told 'pass a name' by commands that
accepted no name flag, making moderation impossible. Mirrors the
--party flag invite already had.
2026-07-04 09:14:19 +00:00
veg
9117f73423 fix: track the executable bit on party
The script was committed mode 100644; a fresh clone could not run
./party, and the bats suite fails with EACCES 126 wherever it invokes
"$PARTY_BIN" directly. Makefile installs masked this via install -m 0755.
2026-07-04 08:34:12 +00:00
veg
f06c599ea7 fix: reject '.' and leading '-' in party names
tmux session_check_name() silently rewrites '.' to '_', so a dotted
party name desyncs from its tmux session and every -t lookup fails
(verified on tmux 3.3a through 3.6b). Leading-dash names can never be
addressed through the CLI parsers.
2026-07-04 07:51:38 +00:00
veg
a4e6dbe672 l'esprit de la fête ! 2026-06-01 18:01:26 +02:00