Same binary, same process, two listeners:
Port 2222: SSH proxy (russh)
Port 9090: Management API (axum)
API endpoints:
GET /api/sessions — active sessions
GET /api/sessions/history — recent history (last 500)
GET /api/stats — aggregate analytics
GET /api/health — server health + version
GET /api/info — server capabilities
Session tracking:
Arc<SessionStore> shared between SSH handler and API
In-memory: active sessions + 500-session history ring buffer
Tracks: auth breakdown, peak concurrent, TPM attested %
Feature flag:
--features dashboard (default on) — includes axum + tower-http
--no-default-features — SSH-only, no HTTP dependency
Config:
[dashboard] section: enabled, listen address
All smoke tests pass. 0 substrate deps.
Signed-off-by: Tyler King <tking@guildhouse.dev>
New crate: bascule-shell (471 lines, 1.8MB binary)
Login shell that detects identity + platform attestation at startup.
Wraps bash/zsh/fish — operator works normally, identity travels with them.
Identity detection (priority order):
1. Entra via WSL2 interop
2. Azure CLI
3. Kerberos TGT
4. Cached OIDC token
5. System user (fallback)
Platform attestation:
TPM 2.0 PCR values via tpm2_pcrread (PCRs 0,1,2,7,10,14)
IMA measurement log hash + count
Keylime agent state
Entra device compliance (WSL2 only)
Composite SHA-256 hash over all evidence
Shell features:
Banner with identity + attestation summary
BASCULE_* env vars injected into inner shell
--info mode for dry-run display
--json mode for machine-readable output
--exec mode for single-command execution
Configurable via ~/.config/bascule/shell.toml
Tested on Fedora with real TPM 2.0:
6 PCRs successfully read from hardware
All env vars propagated to inner shell
1.8MB binary, 0 substrate deps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>