Skip to content

History

Revisions

  • Security-Model: invite secrets stay out of the registry, and why that was measured They are the obvious fourth needle and the answer is counter-intuitive: only inviteHash(secret) is persisted, so the plaintext lives in one frame and is dropped. Measured on a real jam — none of the eight state-dir files, not the daemon log, not the pane. Registering one would require the daemon to start retaining every live invite's plaintext, creating the exposure in order to close it. A discarded secret cannot be printed.

    @roypadina roypadina committed Aug 30, 2026
    28745f7
  • Security: the 0.23.1 findings — the view, the hook secret, and discovery Security-Model: - the browser view bullet becomes two: the URL is a credential and IS the join token when one is set (so a leaked view link is a leaked join link, /token new revokes it and /kick does not), and read-only is real as of 0.23.1 — earlier versions rested it on ttyd's own default, which is version-dependent, and ttyd honours a resize even when it refuses input, so a viewer could shrink the host's live pane from anywhere. - a new section on the third secret and the registry: what the hook secret authenticates, why session.json's lower-case "secret" was the one shape the pattern masker ignored, that holding it alone was sufficient, and why the fix is a registry with two tests as the forcing function rather than a fourth hand-threaded needle. Invite secrets are excluded, with the reason. - the mDNS section gains the direction it never covered: find does not authenticate anybody, anybody on the network can publish a look-alike advertisement, and what changed (no printed --token, address leads, the warning line, invite links as the safe path). Joining-a-Jam: the example listing updated to the new column order and the new footer, why the address comes first, and the token row now points at an invite link as the better answer. Remote-Access: the same two facts about the view URL, at the place people actually turn it on.

    @roypadina roypadina committed Aug 30, 2026
    a941978
  • Install: npm package is @roypadina/claude-jam (the command is still claude-jam)

    @roypadina roypadina committed Aug 30, 2026
    d85061b
  • Install: say that npm 404s, and give the tarball route that works today The page presented `npm i -g claude-jam` as the install command and as "the only Windows path". The package has never been published, so it 404s — and the release doc-drift check runs these commands rather than reading them. Says NOT YET PUBLISHED at the command now, with the `npm pack` + `npm i -g ./claude-jam-0.23.0.tgz` route beside it, and the reason that route is a fair rehearsal rather than a workaround: identical package, identical `files` list, identical `bin` shim. The Windows block gets the PowerShell form of the same thing. Upgrade/uninstall lines are marked "once published". Verified by running it on macOS into a throwaway --prefix: the shim resolves to cli.mjs and prints the launcher's usage.

    @roypadina roypadina committed Aug 30, 2026
    c449b4c
  • Security Model: a Windows file reduces to one ACL entry, a directory does not Measured on the first Windows CI run this project has ever had (2026-08-30), which contradicted the page: it said the `(OI)(CI)` form on a directory leaves the same single entry a file gets. It does not. `icacls` exits 0 and the directory keeps NT AUTHORITY\SYSTEM and BUILTIN\Administrators beside the owner; re-applying changes nothing. Says so now, with what it does and does not mean: a weaker guarantee rather than a hole (both principals read anything on the machine whatever a DACL says), the true assertion CI makes (owner granted, no principal beyond those three — no Users, no Everyone, no Authenticated Users), and the fact that with no Windows host there is no state directory on Windows to begin with.

    @roypadina roypadina committed Aug 30, 2026
    83cebf4
  • Security Model: Windows has no mode bits — say ACL, and say who verified it v0.32 W1 replaces 0600/0700 with an NTFS ACL of one entry on Windows (icacls /inheritance:r /grant:r <user>:F, (OI)(CI) on a directory). The page said 0600 as though it were universal. It now also says the two things a reader needs and would otherwise assume: a failure degrades to profile inheritance rather than failing the write, and the path is verified only by a Windows CI runner — no human has watched it work. NOT PUSHED.

    @roypadina roypadina committed Aug 30, 2026
    458050d
  • Install: npm, and the Windows client stated honestly v0.32 W1 landed a native Windows CLIENT. The page said "macOS and Linux. There is no Windows build", which is now wrong in both directions: hosting is macOS/Linux (or Windows through WSL2), joining includes Windows natively. What the new section refuses to say is "Windows supported". It is implemented, unit-tested on a real windows-latest runner on every push, and has never been run by a human — no toast seen, no sound heard, no key pressed in Windows Terminal, no jam joined. Whoever tries it first is doing the verification, so the page asks them to report what happened. Also: npm as an install path on every platform (the only one on Windows), the prerequisites table corrected to say tmux and claude are what a HOST needs, and the Windows spellings of the state and history paths with the ACL that stands in for 0600 there. NOT PUSHED.

    @roypadina roypadina committed Aug 30, 2026
    4f5856d
  • Security Model + Joining: authenticate before answering anything about the roster (0.22.1) Until 0.22.0 a hello naming somebody already in the jam was refused by name and closed 4409 BEFORE any admission, so the roster was enumerable name by name with no token — unlimited, since the close happened above the pending set. Measured: probing Roy, Dana and Nobody returned 4409, 4409 and a pending knock. The page now states the fix as what it is — ordering, not silence. A token or invite holder is still told at once. A knocker is not told at all, and their clash is settled at admission: they join as Dana-2 and are told so. The host IS told, on the frame they approve from, because otherwise a stranger could make the approval bar read a name that is in the room. Plus the one behaviour change: `name already connected` was the only one of the five invite refusal reasons that closed the socket rather than falling through to a knock. It now falls through like the other four, so reconnecting on your own link while your stale socket is still in the roster is no longer a lockout.

    @roypadina roypadina committed Aug 30, 2026
    5160ff9
  • Security model, files and peer tasks: what the 2026-08-30 review found and fixed Four repairs to the pages, all from measurements rather than restatement: - the wrapped-row scrub was documented as an accepted ceiling; it was measured and is the MAJORITY case ((L-1)/W, so 79% for the 64-hex key at 80 columns, certain below 64), and it is closed in 0.22.1. The remaining case is an escape sequence inside the value. - the free-text answer is raw keyboard access and now says what that meant: it was the one participant text that skipped stripControl, so a CR submitted claude's field and typed the rest as a second, unattributed prompt. Plus the adversarial input set the relay was actually driven with. - jam-uploads/ confinement is a NAME filter, and a name filter cannot see a filesystem: a dangling symlink carried an upload out of the directory until the write became exclusive. And the quota is counted at grant time now, not only at write time. - the peer result's agent-facing copy is fenced, and a result could close that fence. Also: a result's text never reaches /peers log at all. Plus what the invite blob is worth (nothing — every field is re-checked server-side on every use, driven), what its address list is and is not, and the one thing a stranger can learn pre-approval: the roster, name by name, in knock or token mode.

    @roypadina roypadina committed Aug 30, 2026
    9a9cc05
  • Security Model: every way out is scrubbed, not just /export (0.22.0) v0.34 said the host key is scrubbed from /export and reasoned it could not reach a transcript at all, since it is never told to claude. The 0.22.0 release gate found the hole in that: claude runs as the host user with file tools, so any participant can ask it to read host.key, and the answer lands on the pane and in the transcript — both of which the daemon broadcasts. Documents all three paths as a table, the join token getting the same treatment (and why knock mode makes that the bigger of the two), literal-over-pattern and why, and the wrapped-row ceiling with the rotate-the-jam advice that follows from it. Also corrects the ceilings list, which still said claude-jam "strips its own token block and the raw token, and nothing else" on export alone.

    @roypadina roypadina committed Aug 30, 2026
    bbda45c
  • Security Model: host authority is a local file, not a network address (v0.34) 0.21.1 closed F1 by reading the proxy headers a relay cannot suppress. That holds for cloudflared, which was measured, but it is a blocklist: it enumerates what a relay looks like, and the next relay that proxies to loopback without a header on that list re-opens the hole silently. v0.34 makes the answer a 0600 file in the 0700 state dir that only a local process can read, with the header test kept as a second, independent condition. The page now says which two conditions host requires, why a file replaced the inference, that the key grants nothing filesystem access did not already grant, that it is scrubbed and never logged, and that there is no fallback -- a client with no key file joins as a guest and says so.

    @roypadina roypadina committed Aug 30, 2026
    5681140
  • Remote Access: the ~2.5 s before a fresh tunnel hostname routes Timed on the 2026-08-30 tunnel soak, with the log timestamps. Costs nothing to a human pasting a link; matters if you are scripting a join. Pairs with claude-jam 75aef63 (campaign F6).

    @roypadina roypadina committed Aug 30, 2026
    8b8909e
  • Troubleshooting/Agent-Install: the ! incomplete row A claude-jam-<port> directory with no session.json — a start that died before it claimed a session. It used to be invisible to `sessions` and `clean`; it is listed and cleanable now, once nothing holds its port. Pairs with claude-jam 0ac2de5 (campaign F8).

    @roypadina roypadina committed Aug 30, 2026
    4d049c9
  • Files and Export: which renames sanitizing actually does Names the four rules a sender can see happen to their file — the charset filter, the leading dot, the length cut, and (new) trailing dots plus the Windows device names, which are not files at all on Windows. Pairs with claude-jam cf7118b (campaign F5).

    @roypadina roypadina committed Aug 29, 2026
    6b60ae4
  • Hosting: what the adopted re-brief can and cannot notice The re-brief is edge detection over the pane, because a running claude cannot be given a hook. A /compact and a /clear each leave their own marker and each fires; the same event twice with nothing observable between them reads as one. Says so, and names the roster re-brief as the backstop. Pairs with claude-jam 894ed2b (campaign F7).

    @roypadina roypadina committed Aug 29, 2026
    470ce38
  • docs: two lines the 0.21.1 gate's doc check found wrong Install: `npm install` pulls FIVE runtime dependencies, and the sentence said four while listing five (ws, ink, react, @inkjs/ui, ink-text-input). Agent-Install: the expected `claude-jam host` output omitted the `shared-session contract → …/system-prompt.txt` line, which host.mjs prints unconditionally (only --no-system-prompt replaces it with a different line) — so an agent following the page literally sees an unlisted line and has to decide on its own whether the check failed. Added, with a note that `claude profile:` appears only when CLAUDE_CONFIG_DIR is set. Both re-run end to end on 2026-08-30 against the 0.21.1 tree, including `claude-jam end agentcheck`, exit 0, tmux session gone, state dir removed.

    @roypadina roypadina committed Aug 29, 2026
    66f590c
  • the release gate's doc check: five shipped features the entry page called unbuilt Home.md's "Not built yet" list was never revisited after the first commit, so the entry page — the one an agent reads first — was telling people that LAN discovery, join/knock sounds, /nudge, `--uploads auto` and guest-side scrollback do not exist. All five have shipped and all five have a page here. What remains genuinely unbuilt is Windows, and Linux is honest about being thinly proven rather than silently fine. Hosting-a-Jam: the flag table was missing `--history` and `--peer-tasks`, and then claimed `--help` prints the same list. It does not, in either direction — the table also carries four flags `--help` deliberately leaves out. Say what is actually true. Architecture: 283 tests -> 389, two lints -> four, thirteen smokes -> eighteen, and it quoted a SPEC.md heading ("Running the thirteen end-to-end smokes") that has never existed under that name. Joining-a-Jam: /peer and /peers were missing from the only command list a guest gets, on the release that ships them. Verified every form against parseClientLine. Security-Model: the mDNS example record still advertised v0.18.0.

    @roypadina roypadina committed Aug 29, 2026
    60d29e2
  • Peer-Tasks: the two switches, how to say no, and the open question A page for the one feature where something the host's agent asks for costs another human money and attention. It leads with the two switches held by two different people, and it gives "how to say no" its own section — a decline, a one-way `never` for that client session that no host can clear, a cancel for a task already running, and closing the client. The compliance frame is a section rather than a footnote. Every task is one person choosing in the moment to spend their own quota on work they were shown in full, which is ordinary individual usage of each account; whether a coordinated multi-account fan-out counts as ordinary individual usage is NOT settled, and the page says so plainly instead of reassuring anybody. Home gains the row and loses the "not built yet" line for peer tasks.

    @roypadina roypadina committed Aug 29, 2026
    0705d15
  • Hosting: adopt the session you are already in (v0.33) `--resume` restarts a conversation in a pane of claude-jam's own; `claude-jam adopt` shares the one already running, where it stands. The new section says how it is run (from inside the session, or `--pane` from another terminal), that it shows what it resolved and asks before sharing anything, and what happens when there is no tmux at all. Most of it is about what claude-jam does NOT do, because adoption is the first time it points tmux at a server it does not own: reads and typing into the one pane, no session or option or key binding written, and `claude-jam end` taking the daemon and leaving the pane, its session and claude exactly as they were. The two inherent ceilings — no Stop/Notification hooks on a running claude, and no resizing of somebody's own window — are named rather than left to be discovered. The `--resume` row in the flag table now points at it, since "share this session" is what people are usually looking for when they find that flag, and the Ending section says an adopted jam ends differently.

    @roypadina roypadina committed Aug 29, 2026
    a436156
  • Remote-Access: name the upstream Funnel WebSocket risk (tailscale#18827)

    @roypadina roypadina committed Aug 29, 2026
    4245a91
  • wiki: how to look further back, and which of the three limits you just hit Joining-a-Jam gains a "Scrolling back" section — PgUp/PgDn through the host's REAL pane history, Shift+arrows a line, End/G/Esc back to live, the held-frame count, and /history for the transcript. Guests get all of it: it is a read of a screen they are already watching. Troubleshooting leads with the complaint in the words people use it in ("I can only see very little of this conversation") and a table that separates the three limits behind it — what you were shown (--replay), what the jam still keeps (--history, reached with /history), and how far the host pane's own scrollback goes (2000 lines). Plus the honest ones: why the wheel does nothing unless your terminal already sends wheel events, why a re-read page can be two seconds stale, and that F2 no longer eats your scrollback.

    @roypadina roypadina committed Aug 29, 2026
    d56053c
  • wiki: sounds, nudges, and the upload policy that only removes the prompt - Files-and-Export: the three upload policies in a table, the list of protections that do NOT move with them (and the note that smoke-nudge proves each one still refuses while the policy is auto), the 40-file/200 MB session quota and why the fallback line exists, and export's own separate toggle. - Hosting-a-Jam: the four new flags in the flag table; a 'Hearing what needs you' section with the two arrival sounds, why they differ, the once-only knock repeat, and the three toggles. - Joining-a-Jam: /ping and /sound in the command table, and a full section on nudges — what the addressee sees, what the room sees, why it is never queued, the rate limit, the once-only escalation, what idle actually reports, and the opt-in phone config with the topic warning. - Security-Model: a new section, 'The ntfy topic stays on your machine' — the topic is a bearer credential, it lives only in the recipient's config, their own client posts it, and it is never in a frame, an invite link, the protocol or a log. Plus three new entries under 'What to assume': the upload policy is a prompt setting and not a protection, export is separate and stays ask, and a nudge is deliberately not on the approval ladder.

    Claude committed Aug 29, 2026
    cdb436e
  • wiki: finding a jam on your network, and what announcing tells the room Joining-a-Jam leads with finding one, because on the same wifi that is now the easiest way in — the find/join commands, a real listing, and a table of what each `access` value still requires of you. It also answers the three ordinary reasons a jam is not in the list (the host used --no-announce, you are not on that network, this machine has no mDNS tool), none of which is a fault. Security-Model gets the privacy note as a section of its own: the six fields that go on the wire and why each is safe, the list of what is never in it and the fact that this is enforced by an allow-list rather than a redaction pass, and the two consequences worth thinking about — that a jam name is a project name and the default is the directory's, and that on an untrusted network you should turn it off. Plus the point that discovery does not bypass any gate on that page, and the one it would be easy to get wrong: --no-announce hides the name, not the port. That is a bind and a firewall question. Hosting-a-Jam gets the two flags, told apart from --tmux (which is the identifier, not the label), and a short section pointing at the full note.

    @roypadina roypadina committed Aug 29, 2026
    e7c44b6
  • wiki: the ten pages — install, agent-install, hosting, joining, remote, files, security, architecture, troubleshooting Written against what actually shipped (README/MANUAL/SPEC 'what shipped' notes and the real flags in the source). Everything specced but not built — LAN discovery, sounds, nudges, upload auto-allow, guest scrollback, peer tasks, Windows — is listed on Home under 'Not built yet' and described nowhere else. Agent-Install is the page another person's agent is pointed at: the never-do list first, then numbered non-interactive commands with a verification after each, the steps that need a human called out, and a self-test whose expected output was recorded from a real run on 2026-08-29.

    @roypadina roypadina committed Aug 29, 2026
    c0dd31e
  • Initial Home page

    @roypadina roypadina committed Aug 29, 2026
    13d02fc