Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions container/skills/digging/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
name: digging
description: Use owner-approved SSH access to inspect or set up a remote machine, bootstrap a Woltspace colony, and leave a durable local handoff. Use when a human asks a wolt to SSH into, dig into, configure, or prepare another machine. Do not use for Wire pairing or cross-colony IWCL.
---

# Dig into an owned machine

Digging means temporarily using the owner's existing SSH access. The wolt stays
resident in its home colony: connect, do the authorized work, leave a local
handoff for future wolts on that machine, disconnect, and report home.

Prefer `woltspace dig` over invoking `ssh` directly whenever the digging command
is available. The wrapper makes the intended wolt and destination visible,
rechecks the resolved target, preserves the handoff convention, and records a
small non-secret audit trail. It does not create a security boundary against a
wolt running as the same Unix user.

## Find or create the approval

Run `woltspace dig list --json`. Use an existing grant only when its wolt and
destination match the human's request.

If none matches and the named destination is an unambiguous existing SSH alias,
set up the dig grant yourself rather than asking the human to remember CLI
syntax. Choose a short lowercase grant name and run:

```sh
woltspace dig grant newbox newbox --wolt "$WOLTSPACE_WOLT_NAME"
```

Creating the grant only records a pointer to existing SSH access; it copies no
key, certificate, agent credential, or token. If the destination, wolt, or
intended work is ambiguous, ask before granting. Never guess a hostname or
browse unrelated SSH destinations looking for somewhere to connect.

The grant records Woltspace consent; the SSH user's actual permissions remain
the authority. Do not create accounts, keys, tunnels, or broader server access
unless the human separately asks for that work.

## Connect safely

Immediately before the first connection in a task, show the human the grant
name and resolved `user@host:port`, briefly state the intended work, and ask for
confirmation. A stored grant is not standing permission to connect.

Skip that confirmation only when the human's current instruction explicitly
says that permission is not required, says to proceed without asking, or gives
equally clear authorization to connect immediately. Do not infer a permanent
waiver from an earlier task or from the mere existence of SSH access. Once the
human confirms a task, do not repeatedly ask for every bounded command needed
to complete that same task unless the target or scope changes.

Start with a small read-only probe appropriate to the request, for example:

```sh
woltspace dig connect newbox -- hostname
woltspace dig connect newbox -- whoami
woltspace dig connect newbox -- command -v woltspace
```

Use `woltspace dig connect NAME -- COMMAND...` for bounded commands and
`woltspace dig connect NAME` only when an interactive shell is genuinely useful.
The command rechecks the approved SSH host, user, and port and requires strict
host-key verification.

Never disable `StrictHostKeyChecking`, accept a new host key on the human's
behalf, copy a private SSH key, or send credentials through chat, Wire, command
arguments, or handoff files. If SSH authentication or host verification fails,
report the exact non-secret failure and let the human repair their normal SSH
configuration.

## Bootstrap and hand off

Make changes only within the task the human authorized. Preserve existing data
and inspect before overwriting configuration.

The grant's `bootstrap_dir` is relative to the remote SSH user's home and
defaults to `.woltspace/bootstrap`. Create it when needed and leave concise,
human-readable artifacts for the future colony, such as:

- what was installed or configured;
- important paths and decisions;
- checks run and their results;
- incomplete work, open questions, and safe next steps.

Do not write into another wolt's private memory. Do not copy the visiting
wolt's identity, memories, sessions, credentials, or local configuration to the
remote machine. A colony seed may be installed there only when the human has
selected and authorized that seed; digging permission alone does not select one.

## Return and report

Disconnect when the requested work is complete or progress is blocked. Report
the destination, changes, verification, handoff path, and anything left undone.
Do not claim that `woltspace dig revoke NAME` removes real SSH access: it removes
only Woltspace's local grant. The owner must separately remove SSH keys,
accounts, or server authorization when underlying access should end.
169 changes: 169 additions & 0 deletions docs/digging-v0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Wolt digging: product model and experimental roadmap

Digging is a Woltspace feature that lets a wolt request a temporary guest work
session in another colony. Woltspace Wire is only the authenticated, encrypted
transport. Pairing colonies does not grant remote execution.

## Beginner model

- **Home** is the one colony where the wolt exists and keeps its identity,
memory, configuration, and long-lived session history.
- **Wire** lets paired colonies identify and call one another. It carries dig
requests, grants, callbacks, and results, but grants no execution authority.
- **Dig** is an explicitly approved temporary visit into a destination. SSH may
carry that visit, but SSH is an implementation detail rather than the product
concept.
- **IWCL** lets the temporary visiting session explain and coordinate with the
destination's resident wolts while it is there.

Digging is not teleportation, installation, migration, or cloning. A visiting
wolt does not become a resident of the destination colony.

## V0 user story

A human lets a wolt dig into a machine they control. The wolt connects through
ordinary SSH, installs or configures what the machine needs, and leaves durable
local handoff files for the new colony's wolts to find when they wake up. It
disconnects and reports home what it changed and verified.

The handoff may contain a bootstrap note, setup manifest, decisions, next steps,
and verification results. It belongs in an intentionally designated shared
bootstrap location, never another wolt's private memory.

In short: **connect -> set up -> leave a local handoff -> return**.

## Runnable v0: owner-provisioned SSH

The owner configures ordinary SSH access using their existing OS user,
`~/.ssh/config`, agent, and keys. Woltspace records which wolt may dig to the
exact SSH host/user (and optionally a working directory), invokes normal SSH,
and gives the wolt the same remote shell and Woltspace CLI access that owner has
already authorized. The wolt can inspect or set up the machine, disconnect, and
report what changed.

V0 does not create a guest Unix account, transport private SSH keys over Wire,
require a remote Woltspace agent, or provide IWCL across the colony boundary.
The SSH user's existing authority is the real authority; the Woltspace record
is an understandable local consent and audit boundary, not a sandbox.

V0 must still pin or verify the SSH host key, bind consent to the exact host and
user, handle remote PATH and TTY behavior, distinguish home-wolt context from
remote resident files, report interrupted setup honestly, and provide a clear
way to remove both the Woltspace grant and underlying SSH access.

### CLI

```console
woltspace dig grant next-colony my-ssh-alias --wolt n00b
woltspace dig list
woltspace dig connect next-colony
woltspace dig connect next-colony -- woltspace status --json
woltspace dig revoke next-colony
```

`grant` resolves `my-ssh-alias` through the owner's existing OpenSSH config and
records the resulting host, user, and port. Every connection resolves it again
and refuses a changed tuple. SSH runs with `StrictHostKeyChecking=yes`, so an
unknown or changed server key fails instead of prompting the wolt to trust it.
The destination alias is passed as an argument, never through a local shell.

The default remote handoff location is `.woltspace/bootstrap`, relative to the
remote SSH user's home. The command prints this location for the visiting wolt;
v0 intentionally leaves the contents human-readable rather than imposing a
protocol. A useful handoff includes what was installed, paths changed, checks
run, open questions, and next steps. Existing files should be preserved unless
the setup task explicitly authorizes replacing them.

`revoke` removes Woltspace's local consent record. It cannot revoke the Unix
account, SSH key, agent, or server-side authorization; the owner must remove
those separately when access itself should end.

### Disposable installed-wheel proof

Reviewers with Docker can run the complete loopback-only SSH proof:

```console
uv run python test/e2e/dig_ssh_container/run.py
```

It builds the candidate wheel, installs it on both client and disposable SSH
target, publishes the target only on a random `127.0.0.1` port, uses isolated
temporary keys/config/known-hosts/state, pins the generated host key, and proves
grant, installed CLI connection, a separate Unix home, colony bootstrap files,
handoff persistence after reconnect, audit, revoke, refusal after revoke, and
cleanup. It never uses the host's normal SSH configuration or Woltspace state.

## Later: paired-colony visits

Wire could later carry the request, destination approval, callback, and result.
That authorization layer is deliberately not part of this SSH v0.

Cross-tunnel IWCL, a visiting-wolt identity bridge, callbacks, and ongoing
collaboration are explicitly out of v0. Real digging experience should tell us
whether they are needed and what identity and consent model they require.

### Candidate v1 transport: Cloudflare

For machine-to-machine digging, a destination-owned `cloudflared` connector can
reach Cloudflare over outbound-only connections, avoiding a public origin IP or
inbound router port. The durable tunnel is transport; per-dig authorization is
the ephemeral part.

Two increments are possible:

1. Reuse owner-managed SSH keys through a private Cloudflare Tunnel/WARP route.
2. Use Cloudflare Access for Infrastructure for short-lived SSH certificates,
exact user/port policy, and access or command auditing.

The destination owns its tunnel token and never sends it to the visiting wolt.
Direct SSH exposure must still be blocked at the origin if Cloudflare-only
access is intended. The legacy Cloudflare short-lived-certificate application
flow is not a new-deployment target; evaluate Access for Infrastructure instead.

This is unnecessary for two local users on one Mac. A future non-network
local-user transport would be a smaller solution for that case.

## Possible V1 human experience

1. Alice asks to dig to Bobeaver Colony with a short task description and a
destination-relative disposable workspace.
2. Wire delivers the signed and encrypted request from Alice's pinned colony
identity.
3. Bobeaver's human sees the source colony, source wolt, task, target, and short
expiry. They explicitly allow or reject this one dig.
4. Allow creates a random, short-lived, one-use grant bound to the verified
source colony and exact request. The grant returns over Wire.
5. Alice redeems it over the same pinned Wire relationship. Only then may
Woltspace create a constrained guest session.
6. Completion, expiry, or revocation closes the dig. Results and an inert audit
summary may return over Wire.

The same lifecycle may begin without Wire: an owner can manually grant a wolt a
temporary visit to a server they control, with SSH or another Woltspace adapter
providing transport. Wire is the preferred paired-colony convenience path, not
a prerequisite for the general digging concept.

## Security invariants

- A Wire peer is a messenger, not a local authority.
- Pairing never implies permission to dig.
- Approval is local, explicit, exact-request, short-lived, and one-use.
- The request body cannot choose its authenticated source identity.
- Targets are destination-relative and later resolve only inside a newly
created disposable workspace.
- No host path, standing account, SSH private key, relay read capability, or
permanent shell credential crosses colonies.
- The home colony remains authoritative for the visitor's identity and memory.
The destination stores only bounded visit/audit records and never materializes
a second resident wolt.
- The destination can revoke before or during a dig. Active-session termination
is a required integration gate, not yet implemented by the kernel.
- The guest session receives a purpose-built policy and cannot inherit the
destination wolt's normal Auto grant.
- Logs and status omit bearer capabilities and message bodies by default.

## Current implementation

SSH v0 is the only implemented path. Wire authorization, cross-tunnel IWCL,
local-user switching, Cloudflare transport, and short-lived infrastructure
credentials remain design notes, not shipped capability.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ packages = ["src/woltspace"]
"docs/updates.md" = "woltspace/_bundle/docs/updates.md"
"docs/shared-skills.md" = "woltspace/_bundle/docs/shared-skills.md"
"docs/colony-seeds.md" = "woltspace/_bundle/docs/colony-seeds.md"
"docs/digging-v0.md" = "woltspace/_bundle/docs/digging-v0.md"

[tool.hatch.build.targets.sdist]
include = [
Expand All @@ -71,5 +72,6 @@ include = [
"/docs/updates.md",
"/docs/shared-skills.md",
"/docs/colony-seeds.md",
"/docs/digging-v0.md",
"/LICENSE",
]
Loading
Loading