Skip to content

Release 0.5.6 - #111

Merged
makeitfutureDev merged 23 commits into
mainfrom
release/0.5.6
Sep 25, 2026
Merged

makeitfutureDev merged 23 commits into
mainfrom
release/0.5.6

Conversation

@makeitfutureDev

@makeitfutureDev makeitfutureDev commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Release 0.5.6 — candidate f25453f (beta 93b4cd0 + the version cut).

What's in it

  • Composio file staging works with consumer keys — stage_file_for_composio stages through the hosted MCP's workbench (the REST upload rejects ck_ keys); reads from the proven descriptor (symlink TOCTOU closed).
  • Codex uses the staging route — the handoff rule rides every run's Composio identity line.
  • Never recommend a blanket container prune — a managed-block hard rule.
  • Drive sync: a folder linked while empty no longer wedges (empty-listing resync); the WHOLE channel folder now syncs, with instructions/skills/memory/secrets/.git excluded, .driveignore, symlinks excluded, and rclone run in a throwaway container that mounts only the folder, state and key.
  • SSH: Codex over SSH gets the gateway tools, Composio and the channel secrets (codex wrapper, with-secrets); VS Code over SSH opens in the channel folder.
  • Slack Settings: pages are a row of tabs; the inherited-model label names the channel's own harness default. Web admin VPN text no longer duplicated.

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 met
  • npm run check:static, npm run secret-scan, npm run test:security-coverage — pass
  • npm audit --omit=dev --audit-level=high — pass
  • npm run check:dco -- origin/main..HEAD — 14 commits signed off

Live acceptance (Xavier, QA-0925 — recorded in the private QA base)

  • Pass: FSHARE-02 (Claude; Codex after the handoff fix), staging route live, Drive empty-listing recovery (file reached the shared drive), Drive sync pass timeout cleanup, Codex over SSH (owner-verified), SSH-GOV-01 (shell), SSH-GOV-03, CTR-33, CTR-34, IMG-KEYS-01, SEC-UI-REMOVE-02 (both engines), NOTICE-STREAM-01, SLK-SETTINGS-TPL-01, UI-WORKDIR-CONFLICT-01.
  • One SSH hardening item is deferred by owner decision and tracked privately.
  • Not yet executed: the remaining QA-0925 cases (question cards, plugins, public links, …) continue after the release.

🤖 Generated with Claude Code

tbiyss and others added 23 commits September 25, 2026 00:27
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>
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>
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
makeitfutureDev merged commit ec928f4 into main Sep 25, 2026
4 checks passed
@makeitfutureDev
makeitfutureDev deleted the release/0.5.6 branch September 25, 2026 21:07
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.

2 participants