From 2436682a8bd323676a3ba1d4a822106c39f9d5f0 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 23:56:49 -0400 Subject: [PATCH 1/4] Docs: add TurtleTerm integration profile --- docs/integration/turtleterm.md | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 docs/integration/turtleterm.md diff --git a/docs/integration/turtleterm.md b/docs/integration/turtleterm.md new file mode 100644 index 0000000..6f54d1a --- /dev/null +++ b/docs/integration/turtleterm.md @@ -0,0 +1,83 @@ +# TurtleTerm Integration Profile v0 — CloudShell FOG + +## Purpose + +TurtleTerm is the SourceOS policy-aware, agent-addressable terminal workbench for trusted command execution, terminal receipts, agent delegation, and reproducible operator workflows. + +CloudShell FOG is the browser/fog/cloud shell execution plane for session lifecycle, placement, PTY attach, runtime allocation, and audit. + +This profile defines how the two systems should interoperate without creating duplicate terminal truth systems. + +## Ownership boundary + +### CloudShell FOG owns + +- browser / fog / cloud shell session lifecycle +- session placement and runtime allocation +- WSS PTY attach contract +- Kubernetes/fog runtime connector behavior +- CloudShell audit events +- placement metadata (`region`, `node_id`, `tier`, `reasons`) + +### TurtleTerm / SourceOS terminal contracts own + +- local/operator terminal command lifecycle receipts +- command stdout/stderr digests +- SourceOS terminal session/event/receipt schemas +- local agent terminal workflow metadata +- reproducible operator command receipts + +## Integration principle + +CloudShell FOG should reference TurtleTerm receipt contracts where command-level receipts are needed. +It should not invent a parallel receipt schema for local/operator command execution. + +## Correlation model + +A CloudShell session MAY propagate SourceOS terminal context into commands or operator workflows: + +- `SOURCEOS_TERMINAL_SESSION_ID` = CloudShell session ID or derived stable session identifier +- `SOURCEOS_WORKSPACE` = CloudShell workspace / project identifier, if known +- `SOURCEOS_ACTOR_ID` = authenticated subject or mapped actor identity +- `SOURCEOS_POLICY_BUNDLE_ID` = CloudShell policy/profile identifier, if known +- `SOURCEOS_EXECUTION_DOMAIN` = `cloudshell-fog`, `k8s`, `fog`, or more specific runtime domain + +## Event mapping + +| CloudShell FOG concept | TurtleTerm / SourceOS terminal concept | +|---|---| +| `session.created` | `sourceos.terminal.session.v0` | +| `session.attached` | terminal frontend attach context | +| `runtime.allocated` | execution domain / runtime metadata | +| `placement.decided` | placement metadata attached to receipt context | +| command execution inside terminal | `command.started` / `command.completed` receipt events | +| `session.terminated` | terminal session completion / teardown context | + +## Placement metadata + +When CloudShell FOG launches or coordinates a TurtleTerm-backed command workflow, it SHOULD preserve: + +- selected region +- selected node ID +- trust tier +- placement reasons +- runtime image or runtime profile + +These fields should be attached as receipt metadata rather than replacing TurtleTerm's receipt schema. + +## Non-goals + +- CloudShell FOG does not replace TurtleTerm's local receipt schema. +- TurtleTerm does not own CloudShell FOG's placement engine. +- This profile does not require all CloudShell PTY streams to emit per-command receipts by default. + +## Open questions + +1. Should SourceOS terminal schemas move into a shared terminal-contracts repository later? +2. Should CloudShell FOG expose a receipt-export endpoint for completed sessions? +3. Should AgentPlane be the canonical bridge for launching TurtleTerm workflows from CloudShell FOG? + +## Tracking + +- CloudShell FOG: issue #35 +- TurtleTerm: issue #1 From e73acb2aae996165473c14e3263b52280ac3d11e Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 5 May 2026 01:38:28 -0400 Subject: [PATCH 2/4] Add TurtleTerm correlation fixture for CloudShell FOG --- ...loudshell-turtleterm-correlation.v0.1.json | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 fixtures/turtleterm/cloudshell-turtleterm-correlation.v0.1.json diff --git a/fixtures/turtleterm/cloudshell-turtleterm-correlation.v0.1.json b/fixtures/turtleterm/cloudshell-turtleterm-correlation.v0.1.json new file mode 100644 index 0000000..5916a92 --- /dev/null +++ b/fixtures/turtleterm/cloudshell-turtleterm-correlation.v0.1.json @@ -0,0 +1,42 @@ +{ + "schema": "cloudshell-fog.turtleterm.correlation.v0.1", + "cloudshell_session": { + "session_id": "csf-session-0001", + "subject": "human:operator@example.com", + "workspace_id": "workspace:lattice-demo", + "policy_bundle_id": "policy:cloudshell-default", + "placement": { + "region": "us-east-1", + "node_id": "fog-node-01", + "tier": "fog", + "reasons": ["fog-preferred", "healthy", "capacity-ok"] + }, + "runtime": { + "execution_domain": "cloudshell-fog/k8s", + "namespace": "cloudshell-csf-session-0001", + "pod": "shell", + "image_ref": "ghcr.io/socioprophet/cloudshell-fog/runtime@sha256:example" + } + }, + "turtleterm_environment": { + "SOURCEOS_TERMINAL_SESSION_ID": "csf-session-0001", + "SOURCEOS_WORKSPACE": "workspace:lattice-demo", + "SOURCEOS_ACTOR_ID": "human:operator@example.com", + "SOURCEOS_POLICY_BUNDLE_ID": "policy:cloudshell-default", + "SOURCEOS_EXECUTION_DOMAIN": "cloudshell-fog/k8s" + }, + "expected_receipt_context": { + "session_id": "csf-session-0001", + "workspace_id": "workspace:lattice-demo", + "actor_id": "human:operator@example.com", + "policy_bundle_id": "policy:cloudshell-default", + "execution_domain": "cloudshell-fog/k8s" + }, + "correlation_keys": [ + "session_id", + "workspace_id", + "actor_id", + "policy_bundle_id", + "execution_domain" + ] +} From 692cf41c9eb05bc59a75743551d7a9d480d1bddb Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 5 May 2026 01:39:06 -0400 Subject: [PATCH 3/4] Add TurtleTerm correlation fixture validator --- tools/validate_turtleterm_correlation.py | 53 ++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tools/validate_turtleterm_correlation.py diff --git a/tools/validate_turtleterm_correlation.py b/tools/validate_turtleterm_correlation.py new file mode 100644 index 0000000..5c0620d --- /dev/null +++ b/tools/validate_turtleterm_correlation.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Validate CloudShell FOG ↔ TurtleTerm correlation fixture.""" + +from __future__ import annotations + +import json +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[1] +FIXTURE = REPO_ROOT / "fixtures" / "turtleterm" / "cloudshell-turtleterm-correlation.v0.1.json" + + +def main() -> int: + data = json.loads(FIXTURE.read_text(encoding="utf-8")) + assert data["schema"] == "cloudshell-fog.turtleterm.correlation.v0.1" + + cloudshell = data["cloudshell_session"] + env = data["turtleterm_environment"] + expected = data["expected_receipt_context"] + + assert env["SOURCEOS_TERMINAL_SESSION_ID"] == cloudshell["session_id"] + assert env["SOURCEOS_WORKSPACE"] == cloudshell["workspace_id"] + assert env["SOURCEOS_ACTOR_ID"] == cloudshell["subject"] + assert env["SOURCEOS_POLICY_BUNDLE_ID"] == cloudshell["policy_bundle_id"] + assert env["SOURCEOS_EXECUTION_DOMAIN"] == cloudshell["runtime"]["execution_domain"] + + assert expected["session_id"] == env["SOURCEOS_TERMINAL_SESSION_ID"] + assert expected["workspace_id"] == env["SOURCEOS_WORKSPACE"] + assert expected["actor_id"] == env["SOURCEOS_ACTOR_ID"] + assert expected["policy_bundle_id"] == env["SOURCEOS_POLICY_BUNDLE_ID"] + assert expected["execution_domain"] == env["SOURCEOS_EXECUTION_DOMAIN"] + + placement = cloudshell["placement"] + assert placement["region"] + assert placement["node_id"] + assert placement["tier"] + assert isinstance(placement["reasons"], list) and placement["reasons"] + + runtime = cloudshell["runtime"] + assert runtime["namespace"].startswith("cloudshell-") + assert runtime["pod"] + assert "@sha256:" in runtime["image_ref"] + + for key in data["correlation_keys"]: + assert key in expected, f"missing correlation key in expected context: {key}" + + print(f"validated {FIXTURE}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) From b65d304f08c22788992f0a2913db914da4d7f9cf Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 5 May 2026 02:17:39 -0400 Subject: [PATCH 4/4] CI: add TurtleTerm correlation fixture validation --- .github/workflows/turtleterm-correlation.yml | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/turtleterm-correlation.yml diff --git a/.github/workflows/turtleterm-correlation.yml b/.github/workflows/turtleterm-correlation.yml new file mode 100644 index 0000000..96a2760 --- /dev/null +++ b/.github/workflows/turtleterm-correlation.yml @@ -0,0 +1,21 @@ +name: turtleterm-correlation + +on: + pull_request: + push: + branches: [main] + +jobs: + validate-turtleterm-correlation: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Validate TurtleTerm correlation fixture + run: python tools/validate_turtleterm_correlation.py