feat: add remote workspaces and verified deliverables

This commit is contained in:
wuyang
2026-07-26 12:58:04 +08:00
parent 37f83eaac7
commit 0b4d799216
30 changed files with 1595 additions and 55 deletions
+23
View File
@@ -13,6 +13,7 @@ workspace, but not the same Agent loop.
| Visible history | Open WebUI | Open WebUI |
| Run events | Open WebUI | Runtime event store |
| Context and memory | Open WebUI defaults are disabled by policy | Runtime policy and store |
| Workspace files | Authenticated K1412 file browser | Same file browser and volume |
Selecting Work atomically upgrades `(user_id, chat_id)` in the Runtime store.
Subsequent Chat requests for that conversation are rejected even if a client
@@ -33,6 +34,13 @@ Every run records its model tier, strategy version, scheduler version, context
policy, model/tool events, failures, and completion. This event stream is the
foundation for replay, evaluation, and future experiment assignment.
Work completion is evidence-gated. Requests for scripts, reports, code, or
other concrete artifacts are not accepted as complete until a file mutation
has succeeded and a later read, diff, or command has verified the latest
mutation. Bare interactive shell commands are rejected. If the iteration
budget is exhausted without evidence, Runtime returns an explicit incomplete
checkpoint instead of repeating an unverified model claim.
Read-only tools and read-only child Agents may run concurrently. Workspace
mutations are serialized. A child Agent cannot delegate again, and read-only
children receive only read-only tools.
@@ -54,3 +62,18 @@ Only Open WebUI publishes a host port. Runtime, Gateway, Postgres, and Redis
remain unpublishing services. Runtime and Gateway also join an egress-only
bridge so the model API and a future SSH Docker host are reachable without
exposing either service on the host.
## Workspace file path
```text
browser with Open WebUI session
-> /api/v1/k1412/workspace/*
-> Open WebUI backend verifies the user
-> backend mints a short-lived signed identity JWT
-> Workspace Gateway verifies service key + user JWT
-> provider selects only that user's hashed container and volume
```
The file API exposes read-only browse, file download, and streamed directory
archive operations. Paths pass through the same `/workspace` normalization as
Agent tools. The browser never talks to Gateway or Docker directly.
+75
View File
@@ -0,0 +1,75 @@
# Infrastructure map
This document separates shared infrastructure from the parts that define
K1412 Agent behavior.
## Request path
```text
Internet
-> DNS / TLS
-> Nginx Proxy Manager
-> Unraid NAS : K1412 web stack
-> Tailscale + SSH
-> home-node-itx : per-user Docker workspaces
```
## Shared infrastructure
These services make the application reachable or deployable, but changing
them does not change the Agent loop:
| Service | Responsibility |
| --- | --- |
| `git.k1412.top` | Public source repository |
| `docker.k1412.top` | Private immutable container images |
| Nginx Proxy Manager | HTTPS entry and reverse proxy |
| k1412 homepage | Service discovery entry |
| Tailscale | Private NAS-to-execution-host network |
| Unraid Compose Manager | Application lifecycle on the NAS |
Other NAS applications are independent tenants. They are not dependencies of
K1412 Agent merely because they share the host.
## K1412 platform services on the NAS
| Container | Responsibility | Agent core? |
| --- | --- | --- |
| `k1412-agent-web` | Open WebUI auth, RBAC, history, UI, Chat loop | Product shell |
| `k1412-agent-runtime` | Work loop and provider gateway | Yes |
| `k1412-agent-gateway` | Identity, execution policy, workspace lifecycle | Yes |
| `k1412-agent-postgres` | Open WebUI and Runtime durable state | State |
| `k1412-agent-redis` | Open WebUI coordination/cache | State |
| `k1412-agent-bootstrap` | Idempotent admin/tool bootstrap job | Operations |
Only Web publishes a host port. Runtime, Gateway, PostgreSQL, and Redis stay on
private Compose networks.
## Physical execution host
`home-node-itx` is a dedicated, replaceable Docker execution node:
- Intel Core i3-12100F, 4 cores / 8 threads;
- approximately 14 GiB usable RAM;
- 120 GB NVMe system disk;
- 500 GB SSD formatted ext4 and mounted at `/srv/k1412-data`;
- Docker root at `/srv/k1412-data/docker`;
- user workspace volumes stored on the same data disk.
The NAS Gateway connects with a dedicated Ed25519 key and strict host-key
checking. The execution host stores no web/database secrets. Replacing it
requires migrating Docker volumes and changing SSH configuration, not changing
the Agent loop.
## Agent core
The code intended for continuous experimentation is:
- `agent_platform/runtime/loop.py`: loop and evidence policy;
- `agent_platform/runtime/context.py`: context policy;
- `agent_platform/runtime/tools.py`: tools and scheduling metadata;
- `agent_platform/store.py`: events, plans, mode state, memory;
- `agent_platform/gateway/`: isolated execution providers.
Frontend branding, reverse proxy configuration, and registry automation are
important product/operations work, but they are not Agent intelligence.
+59
View File
@@ -0,0 +1,59 @@
# Open WebUI integration
## Responsibility split
Open WebUI is the product shell. It owns account registration, login sessions,
RBAC, administrator approval, conversation history, rendering, and the Chat
mode Agent loop. K1412 does not fork those responsibilities into a second
authentication or chat database.
K1412 Runtime owns Work mode: context selection, durable Work memory, planning,
tool schemas, scheduling, parallel reads, child Agents, evidence gating,
experiments, and run-event persistence. Workspace Gateway owns identity-bound
execution policy and Docker lifecycle.
This split makes the expensive experimental surface small. A new scheduler or
context policy changes Runtime, not the account system or entire frontend.
## Tool and progress rendering
Open WebUI natively understands tool-call and reasoning detail blocks. It also
has a richer live status mechanism for loops that execute inside its own
backend. Work is an external OpenAI-compatible provider, so it cannot mutate
Open WebUI's internal socket status objects directly.
K1412 therefore emits Open WebUI-compatible completed tool detail blocks. Each
tool appears once with:
- a localized action name;
- sanitized arguments (file contents and patches are omitted);
- success or failure state;
- concise plain output instead of the internal JSON envelope.
K1412 deliberately does not expose hidden chain-of-thought. The UI shows
execution progress, tool evidence, completion checks, and concise Agent
summaries. This is enough to inspect behavior without treating private model
reasoning as a product API.
The earlier implementation appended one unfinished and one completed
`<details>` element for every tool call. Since standard provider streaming is
append-only, Open WebUI rendered them as duplicate cards. Runtime now emits
only the completed card; the normal generation indicator covers the active
wait.
## Patches and upgrade cost
Open WebUI is pinned to v0.9.6 and an exact commit. The web image applies a
small patch set during a reproducible build. Product-specific Svelte
components and the authenticated workspace router live under `docker/web/`.
Upgrading Open WebUI requires:
1. updating the tag and commit pin;
2. replaying every patch with `git apply`;
3. building the Svelte production bundle;
4. running authentication, Chat, Work, and file-browser E2E tests;
5. reviewing upstream license changes.
The K1412 Agent loop is not embedded into Open WebUI, so most Work experiments
do not incur this upgrade cost.
+89
View File
@@ -0,0 +1,89 @@
# Operations runbook
## Production layout
- Public URL: `https://agent.k1412.top`
- NAS project: `/boot/config/plugins/compose.manager/projects/k1412-agent`
- Public host port: `12004`
- Execution provider: `ssh-docker`
- Execution host Docker root: `/srv/k1412-data/docker`
- Execution host workspace volumes: Docker volumes named
`k1412-ws-data-<hashed-user-id>`
No credential belongs in this document or repository.
## Deployment
Build and push immutable `linux/amd64` images:
```bash
docker buildx build --platform linux/amd64 -f docker/web.Dockerfile \
-t docker.k1412.top/wuyang/k1412-agent-web:<release> --push .
docker buildx build --platform linux/amd64 -f docker/runtime.Dockerfile \
-t docker.k1412.top/wuyang/k1412-agent-runtime:<release> --push .
docker buildx build --platform linux/amd64 -f docker/gateway.Dockerfile \
-t docker.k1412.top/wuyang/k1412-agent-gateway:<release> --push .
docker buildx build --platform linux/amd64 -f docker/workspace.Dockerfile \
-t docker.k1412.top/wuyang/k1412-agent-workspace:<release> --push .
```
Copy `deploy/docker-compose.yml`, `deploy/docker-compose.override.yml`, and
`deploy/docker-compose.ssh.yml` to the NAS project. Update only immutable image
tags and non-secret settings in the protected `.env`, validate with
`docker compose config`, pull, and recreate.
The SSH override removes `/var/run/docker.sock` from Gateway and mounts the
dedicated SSH directory read-only at `/root/.ssh`.
## Workspace migration
Before changing execution hosts:
1. stop Gateway so no new workspace mutation can begin;
2. enumerate containers and volumes with the
`app.k1412.component=user-workspace` label/name prefix;
3. stop each workspace container;
4. stream a tar archive of each named volume to an identically named volume on
the new Docker host;
5. pull the exact workspace image on the new host;
6. start Gateway with the new SSH target;
7. verify file listing and one read for every migrated volume;
8. retain the old volumes until the verification window ends.
Volume names contain only a user-ID hash, not email or display name.
## Verification
For every release:
```bash
.venv/bin/pytest
RUN_DOCKER_INTEGRATION=1 .venv/bin/pytest tests/test_docker_workspace.py
./scripts/verify-e2e.sh
./scripts/audit-images.sh
```
Production smoke checks must cover:
- anonymous requests are redirected/rejected;
- an approved user can use Chat;
- Chat can upgrade to Work but cannot downgrade;
- Work creates and verifies a real file;
- the file browser lists and downloads that file;
- a second user cannot see it;
- Gateway health reports `ssh-docker`;
- the workspace container exists on the physical execution host, not the NAS.
## Backup priorities
Back up:
1. PostgreSQL;
2. the Open WebUI data volume;
3. Runtime state in PostgreSQL;
4. per-user workspace volumes on the execution host;
5. the protected deployment `.env` and SSH directory through the private
infrastructure backup process.
Redis is reconstructible coordination state and is lower priority than the
database and workspace volumes.
+9 -7
View File
@@ -38,12 +38,14 @@ chosen SSH configuration read-only, and moves Docker access to an SSH-connected
execution host.
Workspace paths are normalized and rejected if they escape `/workspace`.
File browsing and downloads use the same identity boundary. Single-file
downloads are bounded to 128 MiB by default; directory archives are streamed.
## Deployment secrets
Secrets live only in a mode-600 deployment `.env` outside Git. Images contain
no provider or infrastructure credentials. Any API key pasted into a chat
should be rotated before deployment and the replacement placed in `.env`.
no provider or infrastructure credentials. Provider credentials are never
returned to the browser, logged by application code, or committed to Git.
The Web image is rebuilt from a commit-pinned Open WebUI release on
digest-pinned Node and Python bases. RAG/vector, cloud storage, media model,
@@ -64,8 +66,8 @@ remediate them.
## Remaining hardening before hostile public use
Local Docker provides process and filesystem isolation, but the Docker daemon
remains a high-value boundary. Before treating the service as hostile
multi-tenant infrastructure, move workspaces to the dedicated physical
execution host, add egress policy, image signing/scanning, central audit
retention, backup/restore tests, and resource-abuse alerts.
Workspaces run on a dedicated physical Docker host, separated from the public
web and database services. The Docker daemon remains a high-value boundary.
Before treating the service as hostile multi-tenant infrastructure, add
per-workspace egress policy, image signing, central audit retention,
backup/restore drills, quotas, and resource-abuse alerts.