Release 0.5.6 - #111
Merged
Merged
Release 0.5.6#111
Conversation
stage_file_for_composio spent the stored Composio token on the REST upload API, which accepts only project API keys. The tokens a gateway in personal mode stores are consumer keys (ck_...), the hosted MCP's credential, and the REST endpoint rejects them under either header - so every stage failed with 'Invalid API key' and the model told the user their key was broken. The unit tests used a ck_ key against a REST stub, which is how this stayed green. With a consumer key the daemon now stages through the hosted MCP's own workbench: it opens its own MCP session on the same key, writes the file into the sandbox in 768 KB base64 chunks (one request above ~5 MB is rejected with 413), checks the md5 and mints the key with get_mount_file_s3_key. Verified live: that key uploads to Drive from a separate MCP session, which is the daemon/model split. Bytes still never pass through the model; the sandbox name is reduced to safe characters so a file name can never become Python source. Project keys keep the REST route. Consumer-key staging is capped at 25 MB. An upstream problem now answers 'Staging failed:'; only the confinement check answers 'Staging refused:'. The guide says a refusal is final and a failure is reported, not worked around by pushing the bytes through a tool. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
The rule against suggesting podman system prune, podman image prune -a, podman volume prune and docker system prune lived in the operating guide's routing row and administration.md. A live run asked 'what can we clean up?' never opened the guide, measured the disk with its own tools and recommended two of those prunes - on this host they delete every channel's home volume. The run on the other engine read the reference and warned against them. The one-line rule now sits in the managed CLAUDE.md block's hard rules, which every run of both engines loads. The block keeps its 4 KB budget (4,091 bytes): the header note was tightened to make room, and every command is named whole on one line. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
Independent review of the consumer-key staging change found a race that predates it: the staging tool proved the file inside the channel folder with openConfinedFile (O_NOFOLLOW + /proc/self/fd), then closed that descriptor and let staging reopen the file by path, following symlinks. The container can write its own folder, so a symlink swapped in between proof and read would have sent any file the unsandboxed daemon can read. Staging now reads the proven descriptor, bounded to the cap from the same descriptor's size; direct callers get O_NOFOLLOW. No stage ever completed on a consumer-key gateway before this, so it was not usable. Also from the review: every error text is scrubbed of the key and of long base64 runs; the MCP reply must match the request id and carry no method (a server ping is not the answer), SSE data lines are joined; isError and successful:false fail; an overall 10-minute deadline bounds the session, which is ended with DELETE. Only a known project key (ak_) takes the REST route. The sandbox copy is deliberately kept: deleting it breaks the s3key (verified live). Tests cover the symlink swap, a file growing past the cap, session-id reuse, SSE with a leading ping, zero-length and exact-multiple files, every failure shape, key echo on both routes and the deadline; each of the four core claims was mutation-checked red. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
…path Review round 2 (approve with nits) found that reverting the TOOL to close the proven handle and pass a path still left every test green: O_NOFOLLOW catches a swapped final component, but not a swapped parent directory. The tool now takes an injectable stageFile (production uses the real one) and a test asserts staging receives a live descriptor of the proven file and no path; that revert now fails it. Also: the comment about sandbox lifetime no longer contradicts the one about keeping the staged copy; the dead failure-table row is gone; and FEATURES records that on composio-agent backed by the org key the kept copy is listable from any conversation sharing that key. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
Review round 2 (changes required): 'delete every channel's home' was false for three of the four commands - podman image prune -a never touches volumes, and system prune spares named volumes without --volumes. A model that knows podman could argue a false rule away. Each command CAN remove channel homes or the runtime image every channel runs on, so the rule now says that; it also names podman system reset, and keeps the documented removal path (runtime:storage -- --apply only when an admin asks) instead of contradicting it with 'report only'. The block fits its budget in the measured configuration (4,085 bytes); the intro, header note and network line were tightened without changing what they say. The worst switch combination (Admin + Auto, Lean off) was already 4,126 bytes before this rule and is now 4,120; a test stops it growing. The header note's three facts are now asserted. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
Review round 3 (approve with nits): the skill's routing row and administration.md still said the prunes 'delete every channel HOME volume', the claim the hard rule just dropped for being false for some commands - so a run that opened the skill read text contradicting the rule. Both now name the same five commands and the same consequence: they can delete channel HOME volumes or the runtime image. The code comment above the hard rules says the same. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com> # Conflicts: # CHANGELOG.md
Slack Settings resolved an unset channel model through the gateway's default engine, so a Claude-pinned channel on a Codex-default gateway read "Inherited default (gpt-6-sol)" although runs used the Claude default. The label now follows run.js: the template model when it belongs to the channel's harness, else that harness's default. The web admin's unconfigured VPN row also stops appending the server's "VPN is not configured" next to the identical setup hint. Found in QA-0925 (SLK-SETTINGS-TPL-01, SLK-SETTINGS-VPN-01). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
The staging route lived only in the gateway-usage guide's sharing page. A Codex turn that read the guide's front page but not that page (QA-0925 FSHARE-02) base64'd a PDF through the Composio workbench instead of calling stage_file_for_composio, and described it as staging. Every per-run Composio identity line now carries the handoff rule: stage with the identity that runs the destination tool, use an upload link for URL-only tools, and never push file bytes through the workbench to get around staging. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
rclone's --resync of two empty sides succeeds but leaves listings that
record no file, and every later bisync then aborts with exit 7 ("Empty
prior Path1 listing ... Must run --resync to recover"). The gateway had
already written its resync sentinel, so a channel linked to an empty
Drive folder synced once and then failed every tick (QA-0925 GDS-02).
A pass now resyncs again when both prior listings exist and record no
file, or - for channels already wedged - when both were set aside as
header-only .lst-err. Any other missing listing stays an error: after a
deliberate delete-everything rclone sets aside NON-empty listings, and a
resync there would copy the deleted files back. A failed forced resync
keeps its state instead of dropping it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
# Conflicts: # CHANGELOG.md
VS Code Remote-SSH opened an empty window in /home/agent, and its Open Folder dialog started there, so a developer had to climb the tree to reach the channel folder where CLAUDE.md, the skills and the sessions live (QA-0925, reported by Tiberiu). Each SSH session now seeds files.dialog.defaultPath in the container's VS Code machine settings with the channel's effective work folder (custom folders included). The merge keeps VS Code's own keys, follows a changed folder through a sidecar, never overrides a value the developer set, leaves non-JSON files alone, and only warns on failure. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
The five pages were picked from a Page dropdown, which took two clicks and hid which pages exist. They are now one row of tab buttons at the top - General, Resume, MCP, Skills, Secrets - with the open page highlighted. The short names keep the row on one line, which is what the dropdown had been introduced to fix. Each tab carries the same "tab" command the dropdown did, so a Settings view opened while the dropdown shipped still navigates. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
Google Drive sync used to mirror only a Drive/ subfolder of the channel. The owner wants the channel itself in Drive (QA-0925), so the whole work folder is now the local side, with a filters file (case-insensitive, both directions) that keeps out agent instructions and skills at any depth, channel memory, secrets and key files, .git, dependency trees and rclone link stand-ins; a .driveignore file adds a channel's own exclusions and can only ever narrow the sync. An independent review showed that rclone on the host would write Drive files THROUGH a symlink in the work folder - to anywhere the daemon user can write - which the old subfolder sync allowed too. rclone now runs in a one-shot container (podman run --rm, caps dropped, --init, named for forced removal on timeout) that mounts only the work folder at its real path and the sync state, filters and key at a random path per pass; every symlink found is also excluded for the pass. A folder that is or contains the home, the gateway root or the workspace root, a hidden folder of the home, or a workspace folder other than the channel's own is refused. The completed resync now records what it was made for (local root, Drive folder, filters); changing any of them forces a fresh resync from a clean state dir instead of a bisync against the old pair's listings. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
# Conflicts: # CHANGELOG.md
Over SSH, `claude` ran through a wrapper that loaded the session's MCP payload and the developer's channel secrets, but `codex` was the bare CLI: no gateway MCP, no Composio, no secrets (QA-0925, reported by Tiberiu). Each prepared SSH session now also writes Codex's half: codex-args.sh with exactly the -c mcp_servers.*/apps.* overrides a chat turn's Codex gets, a Codex-minted gateway capability and the Composio/toolbox credentials in a 0600 bundle their header helpers read (never argv). A `codex` wrapper sources the secrets, prepends the overrides and, when started from HOME or a parent of the channel folder, starts in the channel folder so its AGENTS.md applies. `with-secrets <command>` runs any other command with the channel secrets. A Codex failure is reported on ssh_session_start and never costs the Claude session. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
Cut the 0.5.6 release section, bump the package and lockfile versions, and record the release decision. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiberiu Socaci <tsocaci@makeitfuture.com>
makeitfutureDev
force-pushed
the
release/0.5.6
branch
from
September 25, 2026 13:02
9b8d45b to
f25453f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release 0.5.6 — candidate
f25453f(beta93b4cd0+ the version cut).What's in it
stage_file_for_composiostages through the hosted MCP's workbench (the REST upload rejectsck_keys); reads from the proven descriptor (symlink TOCTOU closed)..driveignore, symlinks excluded, and rclone run in a throwaway container that mounts only the folder, state and key.codexwrapper,with-secrets); VS Code over SSH opens in the channel folder.No
containers/change — the runtime image is unchanged.Checks (on this exact candidate)
npm run test:coverage— 2924 tests, 2901 pass, 0 fail (23 skipped), coverage floors metnpm run check:static,npm run secret-scan,npm run test:security-coverage— passnpm audit --omit=dev --audit-level=high— passnpm run check:dco -- origin/main..HEAD— 14 commits signed offLive acceptance (Xavier, QA-0925 — recorded in the private QA base)
🤖 Generated with Claude Code