Skip to content

feat: portable coding agent across cli, web, mobile, and p2p#1032

Open
ital0 wants to merge 87 commits into
mainfrom
italomenezes/thunderbolt-cli-mvp
Open

feat: portable coding agent across cli, web, mobile, and p2p#1032
ital0 wants to merge 87 commits into
mainfrom
italomenezes/thunderbolt-cli-mvp

Conversation

@ital0

@ital0 ital0 commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Note

Medium Risk
Touches encryption/device trust and a DB migration for P2P dialability; mitigated by canary proof, trusted-caller checks, upload deny lists, and broad tests, but deploy still needs migration 0021.

Overview
Adds server-managed iroh P2P identity for devices: migration 0021 stores node_id / node_id_attested_at on powersync.devices, and a new canary-gated POST /devices/:deviceId/node-id lets only a trusted caller (with X-Device-ID + valid canarySecret) bind a peer’s endpoint. node_id is deny-listed on PowerSync uploads; revoke, deny, and re-registration clear the binding so revoked/denied peers stay undialable.

CI/release expands for the portable agent stack: path-filtered jobs for shared/agent-core, cli/, and wasm artifact staleness/checksum checks; rust also builds crates/thunderbolt-acp-client. A new CLI release workflow builds darwin-arm64 / linux x64 & arm64 binaries and attaches them (plus SHA256SUMS) to the shared v{version} GitHub Release, hooked from release.yml for all and nightly runs.

Smaller config/tooling tweaks: optional VITE_IROH_RELAY_URL in .env.example, Prettier ignores for committed wasm glue, and a narrowed backend tsconfig shared include list. New powersync upload gate tests cover device trust spoofing and delete isolation.

Reviewed by Cursor Bugbot for commit a4a0393. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown

Semgrep Security Scan

No security issues found.

Comment thread src/acp/iroh/iroh-transport.ts Fixed
@ital0 ital0 self-assigned this Jun 29, 2026
@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown

Preview environment deployed 🚀

Service URL
Marketing / blog / docs https://thunderbolt-pr-1032.preview.thunderbolt.io
App https://app-pr-1032.preview.thunderbolt.io
API https://api-pr-1032.preview.thunderbolt.io
Keycloak https://auth-pr-1032.preview.thunderbolt.io
PowerSync https://powersync-pr-1032.preview.thunderbolt.io

Stack: preview-pr-1032 · Commit: 6be900d44995c95ca607e7f692a0b71e0dd6bf38

Auto-destroys on PR close/merge. Login via the bundled Keycloak realm — demo@thunderbolt.io / demo by default.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown

PR Metrics

Metric Value
Lines changed (prod code) +13685 / -343
JS bundle size (gzipped) 🟢 632.6 KB → 637.3 KB (+4.7 KB, +0.7%)
Test coverage 🟢 77.59% → 77.81% (+0.2%)
Performance (preview) Preview not ready — Render deploy may have timed out
Accessibility
Best Practices
SEO

Updated Fri, 10 Jul 2026 19:21:09 GMT · run #2261

@ital0 ital0 marked this pull request as ready for review June 29, 2026 22:54

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔭 thunder-deep-review (advisory)

Reviewed the diff — no issues to report. ✅ Never approves, never requests changes, never gates merge.
head: b9fe7eb9d374 · mode: deep · deferred 1 item(s) already reported by other bots (best-effort dedup)

Comment thread src/acp/iroh/iroh-transport.ts Fixed
Comment thread backend/src/dal/devices.ts
Comment thread backend/src/dal/devices.ts
ital0 added 23 commits July 10, 2026 14:09
@ital0 ital0 force-pushed the italomenezes/thunderbolt-cli-mvp branch from c8d43a1 to 6be900d Compare July 10, 2026 19:14

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔭 thunder-deep-review (advisory)

Complements the other bots — surfaces only what they did not flag. Never approves, never requests changes, never gates merge.
head: 6be900d44995 · mode: deep · deferred 5 item(s) already reported by other bots (best-effort dedup)

},
}

return [createBashTool(workspaceDir), jailedRead, jailedWrite, jailedEdit]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 Blocking — Workspace jail confines read/write/edit but ships bash unconfined

Heads up — this is the one that worries me. createWorkspaceTools carefully wraps read/write/edit so their paths resolve inside the workspace, but then hands back createBashTool(workspaceDir) with no confinement at all. workspaceDir is only bash's cwd, so the model can walk straight out with cat ../../etc/passwd or an absolute path. This is the confinement layer used for the ACP serve path with untrusted remote peers, and in yolo mode the ACP gate auto-approves bash with no path check — so the jailed read/write/edit tools give a false sense of safety while their bash sibling defeats it. Could we either confine bash's cwd/argv to the workspace, or make it explicit that bash is intentionally unconfined and the jail is path-tools-only (and reconcile that with the yolo auto-approve)?

}
const context = threadCtx('t-persist-retry', { onAcpSessionId })

expect(adapter.fetch(init, context)).rejects.toThrow('persistence failed')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Convention — The .rejects assertion isn't awaited, so it may never actually run

This expect(...).rejects.toThrow('persistence failed') isn't awaited. .rejects.toThrow() returns a promise, and without await the assertion can fail to settle before the test moves on — and the very next line does await drive(adapter, init, context, ...) reusing the same init/context, racing the still-in-flight first fetch. I'd add await in front so the first send's rejection is actually asserted and settled before the retry.

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