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.
This commit is contained in:
veg 2026-07-11 11:57:04 +00:00
parent ff92d812ad
commit be3fb049d2
3 changed files with 30 additions and 30 deletions

View file

@ -92,7 +92,7 @@ The mechanism is identical everywhere: group ownership and mode bits plus `tmux
`party` assumes you already know and trust everyone you add to the group; it is not a public access-control system. Both gates above protect each party, and the **auth gate** (`tmux server-access`) is authoritative, with the filesystem gate as defense in depth. `party` assumes you already know and trust everyone you add to the group; it is not a public access-control system. Both gates above protect each party, and the **auth gate** (`tmux server-access`) is authoritative, with the filesystem gate as defense in depth.
The threat model is **accidents, not adversaries**. `party` runs where everyone already shares the box, so the ownership and symlink gates in front of destructive operations (`close`'s directory removal, moderation) are there so a stale roster, a typo, or two racing `party host` invocations can't remove or hijack the wrong thing that the same checks would also stop a malicious group member is a side effect, not the design goal. New checks should earn their place by preventing a plausible *mistake*, not by closing a hypothetical attack from a friend. The threat model is **accidents, not adversaries**. `party` runs where everyone already shares the box, so the ownership and symlink gates in front of destructive operations (`close`'s directory removal, moderation) are there so a stale roster, a typo, or two racing `party host` invocations can't remove or hijack the wrong thing: that the same checks would also stop a malicious group member is a side effect, not the design goal. New checks should earn their place by preventing a plausible *mistake*, not by closing a hypothetical attack from a friend.
Three honest caveats, with the full detail in `man party`: Three honest caveats, with the full detail in `man party`:

View file

@ -3,49 +3,49 @@
Direction, not promises. Two rules govern everything below (README Direction, not promises. Two rules govern everything below (README
§Security has the long form): §Security has the long form):
- **Accidents, not adversaries.** New checks earn their place by - **Accidents, not adversaries:** new checks earn their place by
preventing a plausible mistake — stale state, a typo, a race — not by preventing a plausible mistake (stale state, a typo, a race), not by
closing a hypothetical attack from a friend. closing a hypothetical attack from a friend.
- **Social, not mechanical.** New features earn their place by - **Social, not mechanical:** new features earn their place by
encouraging people to work together in a terminal, not by adding encouraging people to work together in a terminal, not by adding
machinery. machinery.
## Next small, high value ## Next: small, high value
- **`party knock <name>`** an uninvited group member pings the host - **`party knock <name>`:** an uninvited group member pings the host
via `write(1)`: "veg wants to join fiesta". `party list` already via `write(1)`: "veg wants to join fiesta". `party list` already
shows invite-only parties; knock completes that loop. The feature shows invite-only parties; knock completes that loop. The feature
most likely to cause spontaneous pairing. most likely to cause spontaneous pairing.
- **`party log`** per-party transcript via `tmux pipe-pane` into the - **`party log`:** per-party transcript via `tmux pipe-pane` into the
per-party dir (group-readable so every attendee can grab a copy); per-party dir (group-readable so every attendee can grab a copy);
`party log --stop` ends it. "What did we do last night?" for `party log --stop` ends it. "What did we do last night?" for
collectives, and the audit trail human+AI co-work needs. collectives, and the audit trail human+AI co-work needs.
- **`party clean`** remove the caller's own crash leftovers (dirs - **`party clean`:** remove the caller's own crash leftovers (dirs
they own whose socket is dead), turning the manual `rm -rf` recovery they own whose socket is dead), turning the manual `rm -rf` recovery
in host's error message into a verb. in host's error message into a verb.
## Later ## Later
- **Group ergonomics** the default `party` group needs root and a - **Group ergonomics:** the default `party` group needs root and a
relog before anyone's first party. On boxes where everyone already relog before anyone's first party. On boxes where everyone already
shares a group, `host` could offer (or default to) the caller's shares a group, `host` could offer (or default to) the caller's
primary group when `party` doesn't exist. Fits the trust model; primary group when `party` doesn't exist. Fits the trust model;
costs a little existence-confidentiality. costs a little existence-confidentiality.
- **One liveness primitive** fold `is_party_alive` into - **One liveness primitive:** fold `is_party_alive` into
`party_conn_state`; two concepts where one would do. `party_conn_state`; two concepts where one would do.
- **Matrix** live validation on NetBSD and DragonFly; one - **Matrix:** live validation on NetBSD and DragonFly; one
interactive attach/role/switch pass per release (automated coverage interactive attach/role/switch pass per release (automated coverage
is all non-interactive). is all non-interactive).
## Resist by design, not by neglect ## Resist: by design, not by neglect
- **No network transport.** Same-host is the perimeter; beyond it lies - **No network transport:** same-host is the perimeter; beyond it lies
reinventing ssh. reinventing ssh.
- **No per-pane ACLs.** tmux can't enforce them; faking it with hooks - **No per-pane ACLs:** tmux can't enforce them; faking it with hooks
would be a leaky abstraction. Document the limitation instead. would be a leaky abstraction. Document the limitation instead.
- **No config files, no plugin system, no ACL syscalls.** One POSIX - **No config files, no plugin system, no ACL syscalls:** one POSIX
file that runs on a 30-year spread of UNIXes is the identity; the file that runs on a 30-year spread of UNIXes is the identity; the
2026-04 simplification that removed per-OS ACL dispatch is not to be 2026-04 simplification that removed per-OS ACL dispatch is not to be
unwound. unwound.
- **Watch the file size.** Heavy why-comments are a feature; feature - **Watch the file size:** heavy why-comments are a feature; feature
growth that pushes the single file far past its current size is not. growth that pushes the single file far past its current size is not.

28
party
View file

@ -118,7 +118,7 @@ user_in_party_group() {
# Soft assertion: caller is in TMUX_PARTY_GROUP. Fails loudly with # Soft assertion: caller is in TMUX_PARTY_GROUP. Fails loudly with
# remediation instructions when not. Called by cmd_host before any # remediation instructions when not. Called by cmd_host before any
# filesystem work; the other subcommands don't need it non-members # filesystem work; the other subcommands don't need it: non-members
# are stopped by the FS perimeter itself (EACCES at the per-party dir) # are stopped by the FS perimeter itself (EACCES at the per-party dir)
# and get the friendlier group-gate message in cmd_join. # and get the friendlier group-gate message in cmd_join.
require_caller_in_group() { require_caller_in_group() {
@ -245,7 +245,7 @@ roster_read() {
[ -n "$RR_PARTY_NAME" ] || return 1 [ -n "$RR_PARTY_NAME" ] || return 1
# Pattern parity with cmd_host. The basename glob (party-*:*.d) is # Pattern parity with cmd_host. The basename glob (party-*:*.d) is
# permissive names like 'a b' or 'my.party' match the glob but # permissive: names like 'a b' or 'my.party' match the glob but
# validate_party_name rejects them (dots are banned: tmux rewrites # validate_party_name rejects them (dots are banned: tmux rewrites
# them in session names). Run the canonical validator so the # them in session names). Run the canonical validator so the
# invariant cmd_host enforces on write is also checked on read. # invariant cmd_host enforces on write is also checked on read.
@ -342,12 +342,12 @@ is_party_alive() {
# Classify the caller's relationship to a party socket. Prints exactly # Classify the caller's relationship to a party socket. Prints exactly
# one of: # one of:
# ok live tmux server, the caller is authorized. # ok : live tmux server, the caller is authorized.
# unauthorized live tmux server, but it refused us. CAUTION, the # unauthorized : live tmux server, but it refused us. CAUTION, the
# reason this function exists: tmux answers a # reason this function exists: tmux answers a
# non-allowlisted user with "access not allowed" on # non-allowlisted user with "access not allowed" on
# stderr and EXIT STATUS 0 (verified live on 3.3a, # stderr and EXIT STATUS 0 (verified live on 3.3a,
# 3.5a, and 3.6/SunOS), for every command including # 3.5a, and 3.6/SunOS), for every command, including
# has-session, which then reports any target as # has-session, which then reports any target as
# existing. Exit codes alone cannot distinguish # existing. Exit codes alone cannot distinguish
# authorized from unauthorized. We deliberately do NOT # authorized from unauthorized. We deliberately do NOT
@ -357,8 +357,8 @@ is_party_alive() {
# list-clients writes nothing to stderr, so rc 0 plus # list-clients writes nothing to stderr, so rc 0 plus
# ANY stderr output classifies as unauthorized. Should # ANY stderr output classifies as unauthorized. Should
# tmux ever warn on an authorized call, that degrades # tmux ever warn on an authorized call, that degrades
# to a hidden party never to a false "ok". # to a hidden party, never to a false "ok".
# dead nothing speaking the tmux protocol at that socket # dead : nothing speaking the tmux protocol at that socket
# (stale roster, killed server, AF_UNIX impostor). # (stale roster, killed server, AF_UNIX impostor).
party_conn_state() { party_conn_state() {
_cs_err=$("$PARTY_TMUX" -S "$1" list-clients 2>&1 >/dev/null) \ _cs_err=$("$PARTY_TMUX" -S "$1" list-clients 2>&1 >/dev/null) \
@ -480,8 +480,8 @@ compute_default_party_name() {
# Absolute path to this script, for embedding in tmux server state that # Absolute path to this script, for embedding in tmux server state that
# outlives this invocation (the status-right #() widget runs with the # outlives this invocation (the status-right #() widget runs with the
# tmux server's PATH, which need not contain an installed `party`). # tmux server's PATH, which need not contain an installed `party`).
# $0 forms: absolute — take it; relative-with-slash — anchor to cwd; # $0 forms: absolute, take it; relative-with-slash, anchor to cwd;
# bare word resolve via PATH, falling back to $0 verbatim. No `--` # bare word, resolve via PATH, falling back to $0 verbatim. No `--`
# after command -v/dirname/basename: old illumos userland predates it, # after command -v/dirname/basename: old illumos userland predates it,
# and $0 here never starts with '-'. # and $0 here never starts with '-'.
party_self_path() { party_self_path() {
@ -510,11 +510,11 @@ tmux_party_setup_server() {
# hosts at most one socket so a fixed name is safe. # hosts at most one socket so a fixed name is safe.
notify_script="${sock%/*}/.party-notify" notify_script="${sock%/*}/.party-notify"
# Two heredocs: the first (expanding) pins the tmux binary the party # Two heredocs: the first (expanding) pins the tmux binary the party
# was hosted with a bare `tmux` from the server's PATH may be a # was hosted with: a bare `tmux` from the server's PATH may be a
# different, older binary than $PARTY_TMUX, which is the whole reason # different, older binary than $PARTY_TMUX, which is the whole reason
# PARTY_TMUX exists. The second (quoted) is the static body. A # PARTY_TMUX exists. The second (quoted) is the static body. A
# PARTY_TMUX containing a double quote, $, or backslash would break # PARTY_TMUX containing a double quote, $, or backslash would break
# the pin; that's accepted it's the host's own env var on their # the pin; that's accepted: it's the host's own env var on their
# own party. # own party.
cat > "$notify_script" <<EOF cat > "$notify_script" <<EOF
#!/bin/sh #!/bin/sh
@ -540,7 +540,7 @@ EOF
"$PARTY_TMUX" -S "$sock" set-option -s exit-empty on "$PARTY_TMUX" -S "$sock" set-option -s exit-empty on
party_self=$(party_self_path) party_self=$(party_self_path)
# The #() body is run by the tmux server via sh, so the embedded # The #() body is run by the tmux server via sh, so the embedded
# paths are single-quoted a path containing a single quote, a `)`, # paths are single-quoted: a path containing a single quote, a `)`,
# or `#{` (tmux's #() parser ends at the first unescaped `)`) is # or `#{` (tmux's #() parser ends at the first unescaped `)`) is
# accepted breakage (host's own install path). # accepted breakage (host's own install path).
"$PARTY_TMUX" -S "$sock" set-option -g status-right \ "$PARTY_TMUX" -S "$sock" set-option -g status-right \
@ -975,7 +975,7 @@ EOF
# by the host via `party invite`). Pre-flight here so the user gets # by the host via `party invite`). Pre-flight here so the user gets
# a helpful message instead of an opaque tmux refusal. For an # a helpful message instead of an opaque tmux refusal. For an
# unauthorized caller server-access -l prints its refusal on stderr # unauthorized caller server-access -l prints its refusal on stderr
# with EMPTY stdout (and exit 0 see party_conn_state), so the awk # with EMPTY stdout (and exit 0, see party_conn_state), so the awk
# match comes up empty and we land in the exit-13 branch. # match comes up empty and we land in the exit-13 branch.
acl_line=$("$PARTY_TMUX" -S "$RR_SOCKET" server-access -l 2>/dev/null \ acl_line=$("$PARTY_TMUX" -S "$RR_SOCKET" server-access -l 2>/dev/null \
| awk -v u="$USER" '$1 == u { print; exit }') | awk -v u="$USER" '$1 == u { print; exit }')
@ -1242,7 +1242,7 @@ cmd_list() {
"$RR_HOST_USER" "$RR_PARTY_NAME" "$attendees" "$group_tag" "$RR_HOST_USER" "$RR_PARTY_NAME" "$attendees" "$group_tag"
else else
# Live server, connection refused: we can't count attendees # Live server, connection refused: we can't count attendees
# (list-clients is behind the auth gate its empty stdout # (list-clients is behind the auth gate: its empty stdout
# used to render here as a bogus "0 attendee(s)"), but the # used to render here as a bogus "0 attendee(s)"), but the
# party is real and the caller can ask for an invite. # party is real and the caller can ask for an invite.
printf '%-12s %-30s invite-only (ask %s)%s\n' \ printf '%-12s %-30s invite-only (ask %s)%s\n' \