Skip to content

Dev - #464

Merged
ahmad-ajmal merged 68 commits into
stagingfrom
dev
Sep 23, 2026
Merged

Dev#464
ahmad-ajmal merged 68 commits into
stagingfrom
dev

Conversation

@ahmad-ajmal

Copy link
Copy Markdown
Collaborator

No description provided.

OctoBored and others added 30 commits August 18, 2026 16:35
The star history chart is currently broken due to GitHub stargazer API restrictions, so the README and all localized READMEs now point to a working alternative. Also switch the chart image endpoints from /chart to /svg and the wrapping links to hash-based URLs.
The mkdocs source moves to CraftOS-dev/craftbot-live, where the rest of the
product's web presence lives. Nothing in this repo referenced mkdocs/: no
workflow built it, no script or spec pulled from it, and no file outside the
directory linked into it, so the removal is self-contained.

The one coupling ran the other way. mkdocs.yml generated its default-actions
page by parsing the @action(...) decorators in app/data/action/. That
generator moved with the docs and now runs on demand against a checkout of
this repo, so the catalogue still comes from these decorators and stays
refreshable after actions change here.
CraftBot V1.4.2 update: Connect to external app with multiple accounts, a graph-based Memory system as second brain, safer Living UI updates.
ActivityLogGuard.begin() had no way to tell a batch mate still running
(execute_parallel dispatches all calls before any of them completes)
apart from a row that survived a crash and restart. Track in-flight
idem_keys per guard instance: a restart creates a fresh, empty set, so
the crash-recovery path still fires exactly as before.

Signed-off-by: Amir Fathi <amirfathi.me@gmail.com>
Prevent free-text submission during IME composition in question box
bug:context overflow causing event stream collapsed
Add per-file locks for write_file and stream_edit
CraftBot and others added 23 commits September 18, 2026 12:38
Adds an Origin/Host allowlist plus a per-process session token for /ws, and an aiohttp middleware applying the same judgement to every /api/* route. Also fixes _validate_path to use path containment instead of a string prefix, and sanitises the chat-attachment download name.

Verified: the /ws handshake and the /api guard were attacked with foreign origins, stolen tokens, absent Origin, DNS-rebinding Hosts, other loopback ports and case variants -- all refused. Legitimate traffic still passes in both topologies (run.py static proxy and the Vite dev server) and for the Agent App bridge. run.py now forwards Host/Origin/Sec-Fetch-Site so the proxy cannot launder them; confirmed urllib really does send the forwarded Host rather than overriding it.

Full suite on the branch: 1189 passed, 1 failed -- the same pre-existing failure present on V1.4.3 before this PR.
…452)

* fix: A2App agent-token gate is bypassed by sending any Origin header

* fix validate checks

* fix(a2app): fail closed without agent token, embed apps same-site, warn on destructive GET ops

* fix: LAN Sharing

* fix: validate checks
Applies guard_request to the passthrough and to the WebSocket upgrade, and replaces upstream Access-Control-* with the proxy's own CORS policy. Header copying uses .add() so multiple Set-Cookie survive. Includes a follow-up fix requiring a credential for OPTIONS through a share channel, which was otherwise forwarded upstream uncredentialed.
Removes the observation system. It could never succeed: run_observe_step built Python source by interpolating json.dumps() output, so any action output containing null/true/false raised NameError, and the retry loop then burned up to 60s (600s for observers built via from_dict, whose default disagreed with __init__) before reporting failure. Confirmed unused -- no persisted action, skill or JSON/YAML definition declares an observer, and Action.from_dict reads keys individually so older data carrying one still loads.

Also replaces the process-wide sys.stdout/sys.stderr swap with per-thread routing in the installer, so a worker's output reaches the log panel without capturing every other thread.

Includes a follow-up fix: the new wrapper held sys.stdout unconditionally, but the installer is frozen console=False, so under pythonw both streams are None -- every stray print from a non-routed thread became AttributeError, where print() had previously been a silent no-op. A null-stream stand-in restores that.

Suite on the merged result: 1239 passed, 1 pre-existing failure.
Replaces killing by port-substring and by process name with a ledger of
processes we started, identified by pid + creation time so a recycled pid
can never be mistaken for ours.

Conflict resolution, app/agent_app/manager.py:
#452 moved the tunnel lifecycle out of manager.py into sharing.py, while
this branch was fixing the cloudflared reap in manager.py's old copy.
Taking either side alone loses something: ours drops the reap fix, theirs
resurrects code that no longer belongs here. Resolved by keeping the
sharing.py structure and PORTING the fix to where the tunnel now lives:

  * sharing.py registers each cloudflared it starts in the ledger
    (ROLE_TUNNEL, pid + start time);
  * _kill_orphans reaps by that recorded identity instead of running
    `Stop-Process -Name cloudflared` / `pkill -f cloudflared`, which took
    down every cloudflared on the machine -- including a tunnel the user
    runs for their own production work.

Without this port the mass-kill would have survived the merge silently,
since #452 carried it across into sharing.py untouched.

Suite on the merged result: 1257 passed, 0 failed. This also clears the
pre-existing failure in tests/test_agent_app_launch_lock.py
(TestLiveness::test_a_live_external_app_is_not_dead), which was failing on
V1.4.3 before any of these PRs -- the rewritten listener detection fixes it.
Makes requirements.txt the single source for Python packages; environment.yml
keeps only what pip cannot provide (interpreter, tesseract, libcurl, the
openssl pin, nodejs) and pulls the rest in with `-r requirements.txt`.

Conflict resolution, environment.yml:
#457 had just added psutil to the duplicated conda list that this PR removes
wholesale. Took this PR's side -- psutil arrives via requirements.txt, where
#457 also added it, so nothing is lost. Checked all 49 packages the old conda
list carried: every one is either in requirements.txt or deliberately kept as
conda-only. None dropped.

Note for follow-up, not a defect in this PR: requirements.txt pins nothing
(56 packages, zero ==). That predates this change -- the pins removed here
lived only in environment.yml's duplicate list, and the default installer
path is pip, which has always read the unpinned file. The practical effect
is that a fresh install resolves anthropic/openai to majors the code has
never been run against (this environment works on anthropic 0.83.0 while the
manifest floor says >=0.97.0). Worth a deliberate pinning pass.

Suite on the merged result: 1258 passed, 0 failed.
Documentation only: two AGENT.md files (the live agent_file_system copy and the template), version 8 -> 9.

Verified the claims against the code on V1.4.3 rather than taking them on trust -- EXCLUSIVE_SOURCES, memory.processing_threshold, _merge_triggers and set_skip_unprocessed_logging all exist and behave as described.

The gate was failing on a stale base: the branch was 9 commits behind, so the run was still testing the old validate.ts with its unused verifySystemHashes import, which #452 removed. Updating the branch produced a clean run on all three platforms.
…t-conflation

fix: don't flag an in-flight parallel duplicate as crashed
Port of #443 (merged to dev) onto V1.4.3, which carries identical guard code and the identical bug.

execute_parallel dispatches a whole batch before any call completes, so two identical irreversible calls issue two begin()s with no complete() between them; the second read the first's INTENT row as a crashed prior attempt and told the model the action may already have happened, while the first was still running.

Verified on V1.4.3: the new test fails without the fix and passes with it. Full suite 1259 passed, 0 failed.
…are (#461)

Four items from the V1.4.3 hardening list.

docker.sock + root container: docker-compose.yml mounted the host's Docker control plane into a container that runs model-chosen shell commands, and the image had no USER. Confirmed nothing in the repo ever used the socket (no docker exec, no docker SDK, no DOCKER_HOST) before removing it, along with the Docker CLI and the gnupg/lsb-release that existed only to add its apt repo. Adds a fixed-uid non-root user and no-new-privileges.

.dockerignore: excluded .env but not .credentials/, app/config/settings.json, config.json, agent_file_system/ or logs, so integration tokens and API keys were baked into layers the release workflow pushes to a public registry.

MCP stdio injection: the spawn built a shell string, so one embedded quote in an argument ran everything after it. MCP config is editable in the UI, importable from a bundle and writable by the agent. Now a single exec path; the case a list cannot make safe (a Windows .cmd wrapper, which cmd.exe re-parses however it is spawned) is refused with a message saying what to do. Verified by running the injections.

Bridge token: validate_bridge_token used == on a caller-supplied header guarding every connected integration. Now hmac.compare_digest on bytes.

1311 passed, ruff clean, 53 new tests.

CAVEAT: the Docker image was never built -- no daemon was available. The USER change is the part that needs a real build before a release, and bind-mounted host dirs keep host ownership, so ./workspace needs chown -R 10001:10001 once.
* feat: unify the three install paths, replace the frozen agent

* fix: resolve paths in the install E2E, report platforms with no lock

* fix: parity check

* fix: small ui update

* fix: macOS lock file

* fix: macos test workflow

* ci: macOS debug workflow [vnc]

* revert: macos check

* feat(launcher): ship the native Rust/Slint launcher, retire the Tk installer

* style(launcher): cargo fmt

* style(launcher): cargo fmt, fix clippy redundant_closure

* fix(launcher): make macOS bundle.sh executable

* fix: install problem

* retagged lock files
@ahmad-ajmal
ahmad-ajmal marked this pull request as ready for review September 23, 2026 10:29
@ahmad-ajmal
ahmad-ajmal merged commit 9153c94 into staging Sep 23, 2026
14 checks passed
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.

7 participants