Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v7

# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
Expand Down
50 changes: 41 additions & 9 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
name: Deploy Pages
name: Deploy website

on:
push:
branches: [ "main" ]
branches: ["main"]
paths:
- "pages/**"
- ".github/workflows/pages.yml"
- "demos/terminal/**"
- "docs/**"
- "mk/terminal-demo.mk"
workflow_dispatch:

permissions:
Expand All @@ -24,17 +26,47 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Checkout Ze
uses: actions/checkout@v7
with:
ref: main
path: main

- name: Checkout website
uses: actions/checkout@v7
with:
ref: gh-pages
path: site

- name: Set up Go
uses: actions/setup-go@v7
with:
go-version-file: main/go.mod
cache-dependency-path: main/go.sum

- name: Set up uv
uses: astral-sh/setup-uv@v7

- name: Install VHS and ffmpeg
run: |
make -C main ze-terminal-demo-tools
echo "$HOME/.local/bin" >> "$GITHUB_PATH"

- name: Generate terminal media
run: make -C main ze-terminal-demos-release TERMINAL_DEMO_OUTPUT="$GITHUB_WORKSPACE/site/assets/demos"

- name: Build website
run: uv run --with markdown python3 tools/build.py
working-directory: site

- name: Configure Pages
uses: actions/configure-pages@v5
uses: actions/configure-pages@v6

- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
uses: actions/upload-pages-artifact@v5
with:
path: pages
path: site

- name: Deploy Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v5
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ help-test:
@echo " ze-perf-gate Perf bench (ze DUT) + regression check"
@echo " ze-release-assets Rebuild every release-owned website asset"
@echo " ze-terminal-demos-release Re-record all terminal demos for this release"
@echo " ze-terminal-demo-tools Install native VHS, ffmpeg, and ttyd (macOS/Ubuntu)"
@echo ""
@echo " Escalation: single test -> package -> component group -> ze-verify"
@echo " See docs/contributing/testing.md for the full workflow."
Expand Down
21 changes: 21 additions & 0 deletions cmd/ze/hub/session_factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,24 @@ func TestSessionEditorWithoutReloadFn(t *testing.T) {
assert.False(t, ed.HasReloadNotifier(),
"nil reload function must not register a notifier")
}

// TestDashboardFactoryUsesPublicSummaryCommand verifies that SSH dashboard
// polling uses the registered CLI path rather than the internal RPC nickname.
//
// VALIDATES: monitor bgp reaches the live BGP summary over an SSH session.
// PREVENTS: a healthy dashboard rendering an empty peer table.
func TestDashboardFactoryUsesPublicSummaryCommand(t *testing.T) {
var command string
factory := dashboardFactoryFromExecutor(func(input string) (string, error) {
command = input
return `{"summary":{"peers-configured":3}}`, nil
})

poller, err := factory()
require.NoError(t, err)
output, err := poller()
require.NoError(t, err)

assert.Equal(t, "show bgp summary", command)
assert.JSONEq(t, `{"summary":{"peers-configured":3}}`, output)
}
3 changes: 3 additions & 0 deletions demos/terminal/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**/meta/
**/rollback/
**/ze.audit.jsonl
12 changes: 12 additions & 0 deletions demos/terminal/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM ghcr.io/charmbracelet/vhs:v0.11.0@sha256:9d5fc3dc0c160b0fb1d2212baff07e6bdf3fa9438c504a3237484567302fcf93

USER root

RUN apt-get update \
&& apt-get install --yes --no-install-recommends iproute2 iputils-ping openssh-client procps sshpass \
&& rm -rf /var/lib/apt/lists/*

COPY container-entrypoint.sh /usr/local/bin/terminal-demo-entrypoint

WORKDIR /src
ENTRYPOINT ["/usr/local/bin/terminal-demo-entrypoint"]
184 changes: 184 additions & 0 deletions demos/terminal/cards.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#!/usr/bin/env bash
set -euo pipefail

clear
case "${1:-}:${2:-}" in
launcher:intro)
cat <<'EOF'

Ze command launcher
===================

Goal: discover Ze commands without memorizing the command tree.

This recording will:
1. Open the interactive launcher.
2. Filter the Show commands down to traceroute.
3. Return to the root and find the doctor command.

Watch the breadcrumb and filter labels as the menu changes.
EOF
;;
launcher:recap)
cat <<'EOF'

WHAT THIS PROVED
=================

Type to filter. Enter drills down. Escape moves back.

The launcher is generated from Ze's live command registry, so it stays
aligned with the commands available in the installed binary.

Recording complete.
EOF
;;
cli-dashboard:intro)
cat <<'EOF'

Ze live BGP dashboard
=====================

Goal: inspect active BGP sessions without leaving the CLI.

This recording will:
1. Connect through Ze's SSH management plane.
2. Open the continuously refreshed BGP dashboard.
3. Sort the peer table and inspect one session in detail.

Keys used: s sorts, arrows move, Enter opens detail, Escape returns.
EOF
;;
cli-dashboard:recap)
cat <<'EOF'

WHAT THIS PROVED
=================

One interactive view combines peer state, uptime, message counters,
update rates, and per-session detail. The data refreshes while you work.

Recording complete.
EOF
;;
zefs-config:intro)
cat <<'EOF'

Create ZeFS, then configure Ze over SSH
=======================================

Goal: show the complete configuration path from storage to commit.

This recording will:
1. Create a fresh ZeFS database with ze init.
2. List and validate the stored configuration.
3. Connect to Ze's SSH configuration editor.
4. Change a setting, review the diff, commit, and verify it live.
EOF
;;
zefs-config:ssh)
cat <<'EOF'

STORAGE CHECK COMPLETE
======================

ZeFS now contains a valid active configuration.

Next: connect over SSH, change the default CLI output format, inspect
the pending diff, commit it, then run an operational command.
EOF
;;
zefs-config:recap)
cat <<'EOF'

WHAT THIS PROVED
=================

ze init created the ZeFS database. The SSH editor changed a draft,
show | compare exposed the exact change, and commit made it active.

No configuration file was edited on the running router.

Recording complete.
EOF
;;
rbac:intro)
cat <<'EOF'

Prove role-based command authorization
======================================

Goal: verify that a read-only NOC account can observe but not change state.

The NOC user holds the read-only profile:
run ... default allow, deny "debug", deny "clear"
edit ... default deny

This recording will:
1. Run show version successfully as the NOC user.
2. Ask the same user to clear interface counters.
3. Observe an explicit access-control denial.

Passwords are injected outside the recording.
EOF
;;
rbac:deny)
cat <<'EOF'

Next: test the denied path
==========================

The profile denies every command matching the "clear" prefix.

Ze resolves the command first, then checks the profile, and refuses
before the command runs. The response names the reason explicitly:
"command restricted by access control".
EOF
;;
rbac:recap)
cat <<'EOF'

WHAT THIS PROVED
=================

The same authenticated user could run show version but could not clear
interface counters. Authorization is enforced by the daemon, not by
shell policy, and a refusal is reported as such rather than as a typo.

Recording complete.
EOF
;;
traceroute:intro)
cat <<'EOF'

Trace a live path without the Internet
======================================

Goal: show Ze's one-shot and continuously refreshed traceroute views.

This recording will:
1. Probe 192.0.2.53 through an isolated Linux namespace router.
2. Show the path once as an operational command.
3. Monitor per-hop loss and latency over several rounds.

The lab uses documentation addresses. No public host or DNS is required.
EOF
;;
traceroute:recap)
cat <<'EOF'

WHAT THIS PROVED
=================

Ze sent real ICMP probes through the isolated lab and measured every hop.
The live view continuously updated loss, latency, and variation without
contacting any third-party service.

Recording complete.
EOF
;;
*)
printf 'usage: %s <demo> <intro|checkpoint|recap>\n' "$0" >&2
exit 2
;;
esac
57 changes: 57 additions & 0 deletions demos/terminal/cli-dashboard/demo.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Output artifacts/cli-dashboard.webm
Source common.tape

Hide
Type "export ZE_CONFIG_DIR=/src/tmp/terminal-demos/state/cli-dashboard/config ZE_SSH_PASSWORD=secret123 SSHPASS=secret123"
Enter
Type "/src/demos/terminal/cli-dashboard/run.sh start"
Enter
Wait+Screen /terminal demo ready/
Type "bash /src/demos/terminal/cards.sh cli-dashboard intro"
Enter
Show
Sleep 10s

Hide
Type "clear"
Enter
Show
Type "sshpass -e ssh ze-demo"
Enter
Wait+Screen /ze#/
Sleep 3s
Type "exit"
Enter
Wait+Screen /ze>/
Sleep 3s
Type "monitor bgp"
Enter
Wait+Screen /connected/
Sleep 6s

Type "s"
Sleep 4s
Down
Sleep 3s
Enter
Wait+Screen /Peer Detail/
Sleep 6s
Screenshot artifacts/cli-dashboard.png

Escape
Sleep 3s
Type "q"
Wait+Screen /ze>/
Sleep 2s
Type "exit"
Enter
Wait+Screen /\$ /

Hide
Type "/src/demos/terminal/cli-dashboard/run.sh stop"
Enter
Wait+Screen /terminal demo stopped/
Type "bash /src/demos/terminal/cards.sh cli-dashboard recap"
Enter
Show
Sleep 8s
Loading