You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SharedAuthStore -->|"bind mount (~/.enclave-auth)"| Tool
56
57
FeatureAuthStore -->|"bind mount (~/.enclave-feature-auth/<feature>)"| Tool
58
+
FeatureStateStore -->|"bind mount (~/.enclave-feature-state/<feature>)"| Tool
57
59
Gateway --> DnsNet
58
60
Tool --> DnsNet
59
61
Tool -.->|"resolver/proxy"| Gateway
@@ -166,7 +168,7 @@ The restricted network request flow has a separate
166
168
-**User-defined subcommands**: executables under `~/.config/enclave/commands/{host,session}/` become `enclave <name>` verbs. `cli.Parse` discovers them, registers name-only stub commands (Cobra group "User Commands") so they list in `--help` and shell completion, and intercepts a matching first positional *before*`normalizeArgs`/Cobra so the trailing line reaches the script verbatim (preserving the unknown-command rejection for everything else). enclave flags must precede the name: host commands accept only the global group, session commands accept the full session flag set. `host/` commands exec directly on the host (`os/exec`, exit code/stdin/stdout passthrough, `ENCLAVE_BIN`/`ENCLAVE_PROJECT_ROOT`/`ENCLAVE_CONFIG_DIR` injected). `session/` commands run through the normal run pipeline as a shell-style execution (`opts.Shell=true`, argv `bash -c 'exec "$@"' <name> <container-path> <args>` so the script's shebang is honored via execve).
167
169
-**Session command isolation boundary**: session commands mount only the `session/` tree, read-only, at the fixed neutral container path `/opt/enclave/commands` (`model.UserCommandsContainerDir`) via a dedicated `model.UserCommandMount` — never through `mounts.AddAdditional` (which mirrors host paths and would leak the home layout). No mount/backend code path ever references the `host/` tree, and no enclave host-data directory is otherwise mounted, so host commands stay invisible in-container by construction. Session commands receive no `ENCLAVE_*` env injection.
168
170
-**Detached sessions**: `--background` runs detached tool containers that can be reattached. There is no separate daemon run mode.
169
-
-**Persistent stores**: per-tool/project stores hold tool configs; an optional env store persists env auth and `--pass-env` values when persistence is enabled (default unless `--ephemeral`). Stores are host directories under `~/.local/state/enclave/` bind-mounted into the container (no Docker volumes). See [`docs/runtime/stores.md`](runtime/stores.md) for detailed store lifecycle, auth symlinks, and scoping documentation.
171
+
-**Persistent stores**: per-tool/project stores hold tool configs; an optional env store persists env auth and `--pass-env` values; opted-in mixins receive per-feature/project state shared across tools. Persistence is enabled by default unless `--ephemeral`. Stores are host directories under `~/.local/state/enclave/` bind-mounted into the container (no Docker volumes). See [`docs/runtime/stores.md`](runtime/stores.md) for detailed store lifecycle, auth symlinks, and scoping documentation.
170
172
-**Caches/history**: host-side caches are stored under `~/.cache/enclave/` and shell history under `~/.local/state/enclave/projects/`.
171
173
-**Network isolation**: by default, a gateway sidecar (dnsmasq + transparent proxy) restricts outbound domains. DNS blocks unknown domains, and the proxy is passthrough-by-default with MITM only for hosts that need secret release rewriting unless `network_log=requests` forces MITM for all allowlisted HTTPS.
172
174
-**Declared secrets and HTTP release**: tool profiles and enabled feature manifests can declare `secrets`. Each secret lists env-var aliases and can optionally define `release.http` target hosts/header formatting. Declared secrets are resolved from host env, layered secrets files, or persisted env; when gateway release is enabled, matching secrets are replaced with `ENCLAVE_SECRET_*` placeholders inside the container. The flow is: extension `secrets` config → `PlaceholderResolver` generates placeholders → `SecretMapping` entries written to a JSON file → gateway proxy loads secret release rules and performs header rewriting on HTTPS requests. Plaintext HTTP requests carrying placeholders are denied. This protection is limited to env-var injection: credential files written by auth hooks can still contain the real secret in the config/auth store.
@@ -189,11 +191,12 @@ Persistent stores are host directories under `~/.local/state/enclave/` (honoring
189
191
-**Env store**: `~/.local/state/enclave/projects/<hash>/<tool>/env/` stores persisted env auth data and additional `--pass-env` values when persistence is enabled (default unless `--ephemeral`).
190
192
-**Shared auth store** (when `--auth-scope=shared`): `~/.local/state/enclave/tools/<tool>/auth/<identity>/` stores OAuth files shared across projects for the tool; `<identity>` is `default` or the `--auth-name` slug.
191
193
-**Feature auth store** (when `--auth-scope=shared` and feature defines `authFiles`): `~/.local/state/enclave/features/<feature>/auth/` stores feature auth files shared across tools/projects (for example `github-cli`).
194
+
-**Feature state store** (when an enabled mixin declares `state: true`): `~/.local/state/enclave/projects/<hash>/features/<feature>/state/` stores feature-owned project data shared across tools. It is not created for ephemeral sessions and is independent of auth scope.
192
195
193
196
Other host-side data:
194
197
195
198
-**Embedded asset cache**: standalone binaries extract into `${XDG_CACHE_HOME:-~/.cache}/enclave/assets/<hash>/` on Linux or `~/Library/Caches/org.eclipse.enclave/assets/<hash>/` on macOS. Extraction uses a per-content lock, temporary sibling directory, and atomic rename so concurrent first runs share one complete entry. Missing or invalid entries are recreated from the binary.
196
-
-**QEMU stores**: the experimental QEMU backend mounts the same host-directory stores as the Docker backend (resolved via `internal/backend/hoststore`) into the guest over 9p, so auth, config, and env state are shared across backends.
199
+
-**QEMU stores**: the experimental QEMU backend mounts the same host-directory stores as the Docker backend (resolved via `internal/backend/hoststore`) into the guest over 9p. The store layer supports feature state, but current QEMU bundles disable all mixins, so normal QEMU runs do not request it.
197
200
-**QEMU bundles**: generated microVM bundles live under `${XDG_CACHE_HOME:-~/.cache}/enclave/microvm/<tool>/<hash>/` unless `--image-name` points at an explicit bundle directory.
198
201
-**Caches**: `~/.cache/enclave/<tool>/<hash>/` for package managers and build tools:
| Declared `ports` | Published for every session of the tool | Published when the feature is enabled |
648
+
| `state: true` | Invalid | Opts into project-scoped state shared across tools |
621
649
622
650
## How It Works
623
651
@@ -665,7 +693,7 @@ CLI sets it to the single selected tool):
665
693
666
694
1. Determines current tool from `$TOOL` env var
667
695
2. Sources scripts from `extensions/tools/{tool}/entrypoint.d/*.sh` (tool-specific)
668
-
3. Sources scripts from `extensions/*/feature-entrypoint.d/*.sh` (all features)
696
+
3. Sources scripts from `extensions/*/feature-entrypoint.d/*.sh` (all enabled features), setting `ENCLAVE_FEATURE_STATE_DIR` only for a feature that declares `state: true`
669
697
670
698
### Go Registration (Tools Only)
671
699
@@ -725,6 +753,7 @@ Hooks run in a fixed order during runtime auth preparation:
725
753
3. Optionally add:
726
754
- `install.sh` for custom installation (set `needsRoot: true` if it needs root)
| Config/env/auth stores | Host directories under `~/.local/state/enclave/` (bind-mounted; no Docker volumes) |
47
+
| Feature state |`~/.local/state/enclave/projects/<project-hash>/features/<feature>/state/` for enabled mixins that opt in with `state: true`; shared across tools |
0 commit comments