yatul and Claude Opus 5
ea4890c257
fix(pairing): address review — docs, error mapping, approve feedback, unreadable expiry
...
- docs: device.pair.update and the `permanent` option on approve in
docs/04-gateway-protocol.md, docs/19-websocket-rpc.md and
websocket-protocol.md; the paired-device TTL row in docs/09-security.md
now mentions the admin opt-out.
- store.ErrPairedDeviceNotFound: SetPairingPermanent wraps it in both stores.
device.pair.update maps it to NOT_FOUND and any other store error to
INTERNAL, so a DB failure no longer reads as "not found".
- web UI: approve and make-permanent/set-expiry now toast the server error
and reload the list in `finally`. A partially applied approve (paired, but
the permanent write failed) shows up in the table instead of leaving the
dialog dead-ended.
- SQLite ListPaired: a stored expiry that fails to parse stays 0 (expires,
date unknown) rather than being mistaken for permanent; the UI renders it
as "--" instead of a 1970 date.
Tests: gateway handler error mapping (NOT_FOUND / INTERNAL / OK), sentinel
checks in the PG and SQLite store tests, SQLite unreadable-expiry case.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-09-18 19:26:43 +04:00
Duc Nguyen and ntduc
bb7712a9ff
fix(collaboration): harden delegated task isolation ( #1486 )
...
* feat(collaboration): isolate delegated artifacts and child runs
Isolate delegated inputs and outputs behind secure artifact exchange lifecycles. Scope Agent Link tasks by tenant and root agent, and enforce delegation spawn-tree boundaries. Add process-wide child-run admission and preserve logical media paths across native, MCP, and sandbox execution.
* fix(collaboration): harden delegated task isolation
Enforce tenant and root-agent task scope across migrations and stores. Add exactly-once async completion delivery, delegated sandbox boundaries, and confined artifact and media recovery across runtime surfaces.
* fix(collaboration): recover interrupted async tasks
* fix(collaboration): normalize persisted child-run status
---------
Co-authored-by: ntduc <ntduc@cpp.ai.vn >
2026-07-30 14:17:40 +07:00
Duy Nguyen
f8875e46d6
fix: reject path-based MCP runtime commands
2026-06-20 22:45:35 +07:00
Duy Nguyen
878c33e964
fix: harden MCP stdio validation
2026-06-20 19:29:07 +07:00
Goon
994acfe3a4
feat(cli-credentials): add agent-scoped git credentials
2026-05-31 16:49:23 +07:00
Goon
34bb6121b8
feat(channel-memory): document passive extraction
2026-05-29 20:48:45 +07:00
Duy /zuey/
a591473546
feat(secure-cli): CLI credential adapters framework + git adapter ( #82 ) ( #89 )
...
* feat(secure-cli): Phase 1 schema + storage delta (issue #82 )
Adds `adapter_name` column to secure_cli_binaries and `credential_type` + `host_scope` columns to secure_cli_user_credentials. LookupByBinary LEFT JOIN now projects AdapterName, UserCredentialType, and UserHostScope. Extends SecureCLIStore with SetUserCredentialsTyped(ctx, binaryID, userID, env, credType, hostScope); legacy SetUserCredentials delegates to typed variant with nil/nil for backward compat.
PG migration 73 + RequiredSchemaVersion bumped to 73. SQLite incremental migrations (versions 39–41) + SchemaVersion 42. 7 SQLite + 6 PG integration tests covering schema, round-trip, NULL legacy, LookupByBinary projection.
Fixes #82
* feat(secure-cli): Phase 2 CredentialAdapter framework + passthrough (issue #82 )
Adds CredentialAdapter interface + Injection{ArgvPrefix,Env,Cleanup,ScrubValues} struct. Registry resolves by name; falls back to passthrough for empty/unknown. passthroughAdapter is default no-op — all existing presets (gh/aws/gcloud/kubectl/terraform/gws) behave bit-for-bit identically.
Per-request WithScrubBag(ctx) + AddScrubValuesCtx + ScrubCredentialsCtx for multi-tenant secret isolation (replaces package-global slice). Hook in executeCredentialed between env merge and exec: resolve adapter by bin.AdapterName, reject non-passthrough in sandbox, call Prepare, splice ArgvPrefix, merge Env, defer Cleanup, register ScrubValues.
Audit log security.system_env_injection records adapter name + env key names + argv_prefix_len + sha256(host_scope) — NEVER values. CLIPreset.AdapterName field added; empty default for legacy presets.
12 unit tests covering passthrough no-op, registry fallback + nil safety, Injection shape, hashHostScope determinism, sortedKeys, scrub bag per-request isolation + concurrent + short-value guard.
Fixes #82
* feat(secure-cli): Phase 2b extensibility helpers + psql stub adapter (issue #82 )
Proves CredentialAdapter framework generalizes beyond git. Adds materializeEphemeral(ctx, content, prefix) shared helper — 0600 tmpfile + idempotent atomic.Bool cleanup latch; memfd intentionally rejected (resolves "self" against child process).
Adds psqlAdapter consuming framework end-to-end via PGPASSFILE pattern; libpq-spec .pgpass escaping for `:` and `\`. Registers psql preset with AdapterName: "psql" (production UI for typed creds lands in v2).
Interface validation gate passes: Injection shape unchanged, hook is psql-agnostic, no special branch needed.
Tests: ephemeral write/cleanup/concurrent/zero-content; psql routing/content/escaping/error paths/registration.
Fixes #82
* feat(secure-cli): git adapter PAT + SSH implementation (issue #82 )
Phase 3 — PAT path
- gitAdapter PAT branch via GIT_CONFIG_COUNT/KEY_0/VALUE_0 env (git 2.31+)
so the token never lands on argv, .git/config, or remote URL
- Host-scope enforcement with IDN normalization (golang.org/x/net/idna)
and embedded-userinfo rejection in URL parsing
- CVE-2018-17456 mitigation: resolve remote URLs via `git config --get`
not `git remote get-url` to dodge ext::sh protocol handler injection
- Case-insensitive DenyArgs blocking `-c http.`, `-c credential.`,
`-c core.sshcommand`, `config --global/--system`, `credential-helper`,
bare `daemon`
- New WithExecCwd / ExecCwdFromContext context helpers — fixes a latent
design gap where the adapter's pre-flight `git config --get` ran in
goclaw's daemon CWD instead of the agent's repo
- 14 unit tests covering subcommand routing, host normalization,
scp-form parsing, userinfo rejection, CRLF token rejection,
CVE-2018-17456 regression, DenyArgs preset coverage
- 3 integration tests against a local TLS git-http-backend server
proving end-to-end clone + fetch + host-mismatch rejection with
zero token leakage into the cloned .git/config
Phase 4 — SSH path
- gitAdapter ssh_key branch materializes per-call 0600 tmpfile via
the Phase 2b materializeEphemeral helper, injects GIT_SSH_COMMAND
with -o IdentitiesOnly=yes -o BatchMode=yes
-o StrictHostKeyChecking=accept-new, idempotent cleanup
- ValidateSSHKey using golang.org/x/crypto/ssh rejects
passphrase-protected keys via ErrSSHKeyPassphraseUnsupported sentinel
- 8 unit tests covering passphrase rejection, env shape, cleanup
lifecycle, host-mismatch reuse, malformed-blob rejection
- 3 integration tests proving tmpfile 0600 lifecycle, env propagation
to child process, cleanup-on-exec-failure, no-orphan-on-rejection
- 2 new i18n keys (en/vi/zh) for SSH-passphrase and SSH-key-invalid
Verification: go vet clean, go build ./... clean,
go build -tags sqliteonly ./... clean, go test -race
./internal/tools/ pass, go test -tags integration
./tests/integration/ -run TestGitAdapter pass.
Refs #82
* feat(secure-cli): UI presets + typed credential HTTP path + i18n (issue #82 )
Phase 5. Typed PUT envelope with {error:{code,message}, error_key} for
field-level errors. CliCredentialGitFields React component (PAT/SSH picker,
host_scope input, CRLF→LF normalization, masked-edit). 17 i18n keys × 3
locales (backend + frontend). i18n parity test.
* feat(secure-cli): audit log schema + adapter framework docs (issue #82 )
Phase 6. emitSystemEnvInjectionAudit helper centralizes
security.system_env_injection slog with host_scope_hash (SHA-256 8 hex,
plaintext hostname omitted for PII safety). Audit shape pinned by
TestEmitSystemEnvInjectionAudit_*. New docs: git-credential-adapter.md
(user guide), credential-adapter-playbook.md (R1 implementer guide w/
kubectl/docker/npm/aws/psql worked mappings). 09-security.md § 14
trust-boundary diagram + SSH TOFU + SIGKILL caveats. 03-tools-system.md
§ 8a. Changelog entry.
* docs(journal): issue #82 CLI credential adapters shipped
Retrospective covering 6 commits across phases 1-6: framework, git PAT/SSH, psql stub, UI/i18n, audit log schema, docs. Notes memfd-drop rationale, TOFU/SIGKILL caveats, sentinel-length lesson from audit-shape tests.
* fix(secure-cli): honor per-request scrub bag on success+failure paths (#82 )
Sandbox and host exec paths called the non-Ctx ScrubCredentials, so
adapter ScrubValues registered into the per-request bag during Prepare
(e.g. GitLab glpat-, Bitbucket app-passwords, Azure DevOps PATs, Gitea
tokens, SSH key tmpfile paths) were ignored on stdout/stderr returned
to the agent. Only the package-global regex pass ran — covering ghp_
but nothing else.
Switch all four exec/sandbox call sites to ScrubCredentialsCtx so the
bag is consulted. Also scrub the slog adapter_cleanup_failed line —
os.Remove errors embed the full tmpfile path.
Add 5 regression tests that pin success path, failure path, negative
control (proves the bag is what catches the sentinel), classic-PAT
sanity, and timeout path no-leak.
Locks AC6 against non-GitHub PAT providers.
* fix(secure-cli): address review-pr #89 findings
- ui/web: SSH key Textarea was 'text-xs' on all viewports, triggering
iOS Safari auto-zoom on focus. Switch to 'text-base md:text-xs' so
mobile renders 16px (no zoom) while desktop keeps compact mono font.
- psql adapter: add on-disk pgpass tmpfile path to ScrubValues. psql
echoes 'could not open password file "<path>"' on IO errors, so
the path needs scrubbing alongside the password. Mirrors the git SSH
adapter pattern. Update test assertion accordingly.
- psql adapter: replace literal 'nil' context with 'context.TODO()'
to silence staticcheck SA1012.
2026-05-28 18:17:49 +07:00
Goon
3294fccbad
feat(cli): split env visibility for credentials
2026-05-24 15:14:43 +07:00
Duy /zuey/
425cecb9a3
feat(packages): Phase 2b — apk update flow + pkg-helper v2 protocol ( #900 ) ( #7 )
...
* feat(packages): add apk update flow + pkg-helper v2 protocol
- APK update checker/executor via helper IPC (runtime detection, upgrade scan via apk list --upgradable)
- BREAKING: pkg-helper v2 protocol (5 actions: check_apk/check_pip/check_npm/exec_apk/exec_pip, code/data fields, renewable 10min deadline, apkMutex, 1MB scanner)
- Edition gating: SupportsApk + IsAlpineRuntime double-gate (Standard/Full only)
- Backend 3-branch wiring: alpine/apt/yum routes + update_registry, dep_installer helpers
- i18n: 5 apk keys (EN/VI/ZH catalogs)
- Frontend: source pill Alpine badge, APK in updates-list/summary-bar/update-all modal
- E2E tests: apk_e2e build tag covering checker/executor/helper protocol
- Docs: packages-apk.md, security/changelog updates
- Plans + reports under plans/260417-1500-packages-update-phase2b-apk-pkghelper/ + plans/reports/
* docs(packages): journal Phase 2b apk + pkg-helper v2
2026-05-11 15:41:27 +07:00
viettranx
cd1b3f267b
docs: condense security, rpc, auth, evolution body text
...
- 09-security: compress 9-bullet edge-case list to 6-row Attack Surface/Mitigation table
- 20-api-keys-auth: replace auth.go:tokenMatch + router.go:handleConnect citations with behavior descriptions; remove RoleFromScopes() file ref
- 21-agent-evolution: remove resolver.go:346 code block + loop.go/loop_history.go line citations, replace with behavioral descriptions
- 19-websocket-rpc: already clean (no body-text .go:line refs)
2026-04-19 15:41:16 +07:00
viettranx
463d3d1c5d
docs: replace file-reference lists with module tables (batch B)
2026-04-19 15:38:26 +07:00
viettranx
7e2e66c095
fix(security): hard-deny ungranted exec for registered CLI binaries
...
Closes credential-scope bypass where an agent without a `secure_cli_agent_grants` row could still invoke a registered binary via shell fallthrough and pick up inherited env (`$GH_TOKEN`) or on-disk OAuth state. Registration is now an authorization boundary, not only a credential-injection hint.
- Add `SecureCLIStore.IsRegisteredBinary` on PG + SQLite backends — case-insensitive, tenant-scoped.
- New gate branch in `internal/tools/shell.go` (after normalization, before exec approval) with shell-wrapper unwrap depth 3 (sh/bash/zsh/dash -c, env K=V, nohup, stdbuf, timeout), 2s DB-lookup timeout, fail-CLOSED on error. New log events: `security.credentialed_binary_denied`, `security.credentialed_binary_gate_error`, `security.credentialed_binary_wrapper_too_deep`.
- Env scrubbing on host fall-through (`internal/tools/env_scrub.go`) strips static credential keys (GH_TOKEN, AWS_*, OPENAI_API_KEY, …) plus dynamic keys from tenant's registered binaries; preserves HOME/PATH/TERM/LANG/USER/TZ.
- Subagent ExecTool registration (`cmd/gateway_agents.go` → `buildSubagentToolsRegistry`) now receives the same `SecureCLIStore` — parent can't delegate to a child to bypass the gate.
- Binary names lowercased on Create/Update for symmetry with case-insensitive lookup.
- Thread `pgStores.SecureCLI` into `setupSubagents` in `cmd/gateway.go`.
- 25+ unit tests (gate, env-scrub, SQLite IsRegisteredBinary) + 5 PG integration tests (deny-ungranted, allow-granted, unregistered-unchanged, is_global-not-denied regression, shell-wrapper-bypass denied). All green.
2026-04-17 19:02:53 +07:00
viettranx
843b550651
feat: runtime packages UI, pkg-helper, configurable shell deny groups ( #244 )
...
Runtime package management with security hardening:
- pkg-helper: root-privileged daemon for apk install/uninstall via Unix socket
- HTTP API: /v1/packages (list/install/uninstall/runtimes), admin role required for writes
- Shell deny groups: 15 configurable groups (per-agent overrides via context)
- Packages UI: Web page for managing system/pip/npm packages with confirmation dialogs
- Docker: privilege separation (root entrypoint → su-exec drop), init for zombie reaping
- Security: umask socket creation, persist file validation, deny pattern hardening
(Node.js fetch/http, Python from/import, curl localhost, sensitive env vars)
- Auth: empty gateway token → admin role (dev/single-user mode)
2026-03-17 19:50:26 +07:00
viettranx
4678065887
refactor: remove dead quality gates / hook engine code
...
The delegation system this depended on was previously removed,
leaving internal/hooks/ as dead code with zero imports. Remove
the entire hook engine, UI config section, protocol types, i18n
keys, and all documentation references.
2026-03-17 18:00:09 +07:00
Viet Tran
037d18f711
docs: comprehensive audit and update of all documentation ( #231 )
...
* feat(ui): improve kanban UX, fix dialog scroll, remove delegation page
- Kanban: reorder columns (blocked after pending), show blocked-by info
on cards, clickable blocker links in task detail, framer-motion card
animation between columns
- Dialogs: standardize scroll pattern across all modals — header fixed,
scrollbar flush with outer edge via negative margin trick
- Remove delegation page, types, events, i18n, routes, and all references
- Fix activity_logs NULL jsonb scan error (COALESCE)
- Board header: show text labels on action buttons (desktop)
* docs: comprehensive audit and update of all documentation
- Update Go 1.25 → 1.26, PostgreSQL 15+ → 18 across all docs
- Add 10 missing internal modules to CLAUDE.md project structure
- Expand provider docs from 2 to 6 packages (Anthropic, OpenAI, DashScope, Claude CLI, ACP, Codex)
- Add 8 missing store interfaces to data model docs (22 total)
- Update bootstrap files from 7 to 13 templates
- Expand tool inventory from ~35 to 60+ tools with media/KG/credential categories
- Fix Team Task Board: add blocked status, 3 missing actions, V2 versioning, delegate restrictions
- Remove all references to removed features: handoff, delegate_search, evaluate_loop, agent_links
- Fix lane defaults (2/4/1 → 30/50/100/30), ghost file references, models.list → providers.models
- Add SecureCLI, snapshot worker, cost calculation, pairing security docs
- Comprehensive changelog catch-up
- Trim docs/03-tools-system.md to 800-line limit
2026-03-16 22:51:57 +07:00
Goon
75c570e951
feat(security): credentialed exec + HTTP RBAC + API key cache ( #197 )
...
- Secure CLI credential injection via AES-256-GCM encrypted env vars
- API key management with fine-grained RBAC scopes
- resolveAuth/requireAuth middleware across all 25+ HTTP handlers
- In-memory API key cache with TTL, negative caching, pubsub invalidation
- Sandbox-first execution (fails if unavailable, no silent fallback)
- Credential scrubbing, constant-time token comparison, Admin-only CLI creds
- SQL migration 000020: secure_cli_binaries + api_keys tables
- 14 unit tests for cache and RBAC with race detector
Closes #197
2026-03-15 20:13:18 +07:00
Thieu Nguyen
8ad580521d
refactor: deprecate standalone mode, managed mode is now default ( #126 )
...
* refactor: remove managed/standalone mode distinction from codebase
Standalone mode is deprecated; managed mode is now the only mode.
Remove redundant "managed mode" qualifiers from comments, docs,
and error messages. Error strings now reference "database stores"
instead of "managed mode" for clarity.
* improve(onboard): streamline onboard process and env setup
Simplify onboard wizard, extract helpers to dedicated file,
update env example and entrypoint for default managed mode,
clean up prepare-env script, update i18n catalogs.
2026-03-11 07:27:38 +07:00
Viet Tran
6895e369f6
refactor: remove standalone mode, consolidate to managed-only (PostgreSQL) ( #70 )
...
- Remove standalone mode code: file-based stores, standalone gateway,
heartbeat service, SQLite memory, standalone docker-compose
- Rename docker-compose.managed.yml → docker-compose.postgres.yml
- Clean up ~130 Go comments referencing "managed mode" qualifier
- Simplify docker-compose.yml env vars (providers/channels via web UI)
- Update .env.example to essential vars only (token + encryption key)
- Add setup wizard UI (provider → agent → channel bootstrap flow)
- Add logs.tail WebSocket handler for live log streaming
- Add cursor-pointer to interactive UI components
- Clean up config page (remove standalone-only sections)
- Update README and docs for managed-only architecture
2026-03-06 18:51:11 +07:00
viettranx and Claude Opus 4.6
e7939de84b
docs: overhaul documentation for v0.2–v0.5 features
...
Add new docs for agent teams (11) and extended thinking (12).
Major rewrite of channels/messaging (05) with Telegram forum topics,
Feishu streaming cards, Zalo Personal. Update providers (02), tools (03),
bootstrap/skills (07), security (09), architecture (00), scheduling (08),
and tracing (10) with current implementation details.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-03 19:20:53 +07:00
viettranx
31f7e1e22e
feat: add prepare-env.sh script, update documentation, and refine session scheduling with new lanes and stop commands.
2026-02-26 18:48:13 +07:00
Viet Tran and Claude Opus 4.6
f3f4c67b36
Initial commit: GoClaw AI agent gateway
...
Multi-agent AI gateway with WebSocket RPC, HTTP API, and messaging channel integrations.
Go port of OpenClaw with multi-tenant PostgreSQL, per-user isolation, security hardening,
and production observability.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-22 14:58:07 +07:00