Skip to content

lody: let a box attach a file — the cloud-token guard no longer preempts the local transport - #156

Merged
pythonlearner1025 merged 1 commit into
mainfrom
lody-attachment-guard-fix
Sep 1, 2026
Merged

lody: let a box attach a file — the cloud-token guard no longer preempts the local transport#156
pythonlearner1025 merged 1 commit into
mainfrom
lody-attachment-guard-fix

Conversation

@pythonlearner1025

Copy link
Copy Markdown
Member

The defect

Canary QA reported COMPB-1. Every + attachment on a box fails. The message is
"Missing workspace or auth token". No MKCOL and no PUT reaches dufs
(BUG-CA-01). "Retry upload" does nothing, because a retry enters the same guard
(BUG-CA-02). The verifier reproduced this twice in a real browser.

The cause

The cause is upstream, and it is an order-of-operations bug. Three attachment
entry points hold a local handoff. At each one, if (!workspaceId || !authToken)
stands in front of that handoff.

The local handoff needs no cloud token. Seam patch 3 opened it to a non-Electron
bridge, and test/lody-attachments.test.ts proves that the channel behind it
stages bytes on the box. The verifier also called
localProjects.sendSessionFileLocal by hand on the same page: dufs answered
MKCOL 201 and PUT 201. A box holds no cloud token, so the guard rejects the
attachment before that path can run.

This is not a BlitzOS-only concern. apps/electron composes the same local
transport, and the root AGENTS.md forbids authenticated product-cloud requests
from the OSS desktop entry. A local-only Electron build holds no token either,
and loses the same control.

The change

Seam patch 8, declared in vendor/lody/BLITZ-PATCHES.md. Five hunks in two
vendored files, and all five carry one idea.

File Hunks Effect
components/sessions/session-chat-input-area.tsx 4 The file path moves the handoff above the guard. The image path admits a missing token when the local transport is there, and throws into the degrade-to-file catch that upstream already wrote.
hooks/use-chat-landing-file-draft.ts 1 The same move on the landing composer.

The guard is moved, not deleted. It still owns the cloud path below the local
one. A browser with no token and no bridge still fails with the same message.

plans/evidence/lody-attachment-guard-pr.md holds the upstream PR sketch. Drop
this seam patch when upstream merges the fix.

Safety when a cloud token IS present

Every hunk is inert with a token. Both moved blocks keep their original
condition and gain only workspaceId &&, which the guard below them asserted
anyway. Upstream already ran the local fast path FIRST whenever
canSendFileLocally was true, so a token holder on a machine with a bridge
takes the same branch as before. A token holder with no bridge declines the
local block and falls into the unchanged guard and the unchanged cloud upload.
The image guard only widens: !authToken alone no longer bails, but a request
with a token never reached that bail.

test/lody-attachment-guard.test.tsx checks this rather than asserts it. It
mounts the REAL vendored landing hook over a stub bridge and stages a file in
three cases: no token with a bridge (the fix), no token with no bridge (the same
refusal), and a token with a bridge (unchanged). The in-session half needs a
daemon that CI does not have, so the test pins that half at the source, under
the rule lody-surface-tabs.test.tsx already applies.

What this does not do

hooks/use-chat-landing-image-draft.ts carries the same guard and is left
alone. That hook has no local handoff and no degrade-to-file fallback, so there
is nothing to move in front of the guard. An image on the LANDING therefore
still fails on a box, while the same image inside a session becomes a file
attachment. BLITZ-PATCHES.md §8 records that gap. A fix for it adds behaviour
upstream does not have, and it belongs in a change of its own.

Gates

  • npm run typecheck — clean.
  • npm run lint:gate — passed; 74 anti-slop findings, all at baseline.
  • BLITZDEV_MANAGED=1 npm test — 91 files, 765 passed, 6 skipped, exit 0.

An earlier run failed two daemon-backed suites on boot timeouts. Two other full
suites ran on the same box at that moment, and both of those runs failed as
well. The clean run above ran alone.

🤖 Generated with Claude Code

https://claude.ai/code/session_01P92fhMxx375D1oYp5gPqW6

…pts the local transport

Seam patch 8. Every `+` attachment on a BlitzOS box failed with "Missing
workspace or auth token" before a single MKCOL or PUT was issued (canary QA
COMPB-1, BUG-CA-01), and "Retry upload" re-entered the same guard and did
nothing (BUG-CA-02).

The cause is upstream and it is an ordering bug: at each of the three entry
points that HAVE a local handoff, `if (!workspaceId || !authToken)` stood in
front of it. That handoff needs no cloud token — seam patch 3 already opened it
to a non-Electron bridge, and `lody-attachments.test.ts` already proved it
stages bytes on the box. A local-only Electron build has no token either, so it
loses the same control.

Five hunks in two vendored files, all one idea. The two file paths move the
handoff above the guard; the in-session image path admits a missing token when
the local transport is there and throws into the degrade-to-file `catch`
upstream already wrote. Every hunk is inert with a token present.

`use-chat-landing-image-draft.ts` is deliberately not patched: it has no local
path to move in front of, so an image staged on the LANDING still fails.
BLITZ-PATCHES.md records that gap.

Declared as seam patch 8 in vendor/lody/BLITZ-PATCHES.md, with the upstream
sketch at plans/evidence/lody-attachment-guard-pr.md. Pinned by
packages/webapp/test/lody-attachment-guard.test.tsx, which drives the real
vendored landing hook over a stub bridge across all three token/bridge cases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013voh4zgczP2jmPrS2ERrav
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