Skip to content

feat: recombine DD + bastion into workspace, scaffold EE capture, sidebar categories#164

Merged
posix4e merged 3 commits intomainfrom
feat/recombine-workspace
Apr 20, 2026
Merged

feat: recombine DD + bastion into workspace, scaffold EE capture, sidebar categories#164
posix4e merged 3 commits intomainfrom
feat/recombine-workspace

Conversation

@posix4e
Copy link
Copy Markdown
Contributor

@posix4e posix4e commented Apr 20, 2026

Summary

The "one big chunk" from the plan — three things that are simpler done together than apart because they all touch bastion's public shape and DD's boot path.

(1) Recombine into a monorepo workspace

  • Root `Cargo.toml` becomes workspace manifest.
  • `crates/dd/` — `devopsdefender` binary (cp + agent modes). All of `src/` moves here verbatim.
  • `crates/bastion/` — `bastion` binary, seeded from the bastion repo at v0.2.
  • `crates/dd-common/` — shared types; starts with `BlockRecord`.

`apps/bastion/workload.json` flips `github_release.repo` to `devopsdefender/dd`. DD's release asset now carries both binaries. bastion repo to be archived in a follow-up.

Two release tracks:

  • `release.yml` (adjusted): builds both binaries on `dd-v*` tags.
  • `release-bastion.yml` (new): triggers on `bastion-v*` tags; rebuilds just bastion; publishes GH release.

(2) EE capture scaffold

  • `crates/bastion/src/capture.rs` — unix-socket listener, parses LDJSON (`spawn` / `out` / `exit`) from a future patched easyenclave. Logger-only in this PR; next PR wires records into `Manager` as workload-kind sessions.
  • `--capture-socket ` CLI flag on `bastion serve`.
  • `workload.json` passes `/run/ee/capture.sock` so bastion is ready when EE upstream emits.

(3) Sidebar categories

  • `BlockRecord` + `SessionInfo` gain `kind` ("shell" today; "workload", "claude", "codex" later).
  • Inline SPA groups the sidebar: Shells / Workloads / Claude / Codex with empty-state placeholders. Only shells expose a close button.

Test plan

  • `cargo build` and `cargo test --workspace` pass (21 dd + 5 bastion incl. 4 new capture-parser tests)
  • `cargo fmt --check` and `cargo clippy --workspace --all-targets -- -D warnings` clean
  • PR preview deploy builds both binaries, CP deploys, bastion runs at `block.` with the new sidebar categories visible (Shells section populated; Workloads/Claude/Codex empty until follow-up)
  • Post-merge tag `dd-v*` triggers a unified rebuild + deploy
  • Post-merge tag `bastion-v*` rebuilds just bastion

Follow-ups (explicit non-goals here)

  • Archive `devopsdefender/bastion` repo with a redirect README.
  • Wire `capture.rs` records into `Manager` so workload sessions actually appear under the "Workloads" sidebar category.
  • Upstream easyenclave patch to emit on the capture socket.

🤖 Generated with Claude Code

posix4e and others added 2 commits April 20, 2026 20:41
…ebar categories

The "one big chunk" from the plan: three things that are simpler done
together than apart because they all touch bastion's public shape and
DD's boot path.

(1) Recombine into a monorepo workspace.
- `Cargo.toml` at the repo root becomes a workspace manifest.
- `crates/dd/` — the `devopsdefender` binary (cp + agent modes). All
  of `src/` moves here verbatim; no code changes.
- `crates/bastion/` — the `bastion` binary, seeded from
  `devopsdefender/bastion` at the v0.2 tag. Deployed as a workload
  onto existing DD agents via `dd-deploy` the same way it was before.
- `crates/dd-common/` — shared types; starts with `BlockRecord` as a
  proper Rust type that bastion emits and any later aggregator
  (Tauri app, CP proxy) will consume.

`apps/bastion/workload.json` flips `github_release.repo` from
`devopsdefender/bastion` to `devopsdefender/dd` — DD's release asset
now carries both `devopsdefender` and `bastion.x86_64` binaries. The
bastion repo will be archived with a redirect README in a follow-up.

Two release tracks:
- `.github/workflows/release.yml` (existing, adjusted): builds both
  binaries on `dd-v*` tags and publishes them together. CP+agent
  redeploy path unchanged.
- `.github/workflows/release-bastion.yml` (new): triggers on
  `bastion-v*` tags; rebuilds just the bastion binary; publishes a
  GH release. A follow-up workflow can dd-deploy from there onto live
  agents.

(2) EE capture scaffold.
- `crates/bastion/src/capture.rs` (new) — binds a unix socket at
  `--capture-socket <path>`, accepts connections, parses LDJSON
  records emitted by a (future) patched easyenclave: `spawn`, `out`,
  `exit`.
- `crates/bastion/src/bin/bastion.rs` — new `--capture-socket` flag.
- `apps/bastion/workload.json` — cmd includes
  `--capture-socket /run/ee/capture.sock` so bastion is ready to
  listen as soon as EE's upstream patch lands.
- This PR keeps the handler as a logger-only scaffold; the next PR
  wires `spawn`/`out`/`exit` into `Manager` as workload-kind sessions
  once EE is emitting and the sidebar rendering is proven.

(3) Sidebar categories.
- `BlockRecord` and `SessionInfo` gain a `kind: String` ("shell" |
  "workload" | future: "claude", "codex"). Existing shell path sets
  `kind = "shell"` everywhere a session/block is constructed.
- Inline SPA (`crates/bastion/src/page.html`) now groups the sidebar:
  Shells / Workloads / Claude / Codex, with empty-state text per
  category. Only shells show a close (`×`) button — other kinds are
  owned by their respective sources.

Builds clean; `cargo test --workspace` passes (21 devopsdefender +
5 bastion including 4 new capture-parser tests); clippy
`-D warnings` clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plain `apps/bastion/workload.json` pointing at `devopsdefender/dd`
with no tag made easyenclave fetch from `latest` — which predates
this PR and therefore has no `bastion.x86_64` asset. Preview CP
panicked on boot with:

  easyenclave: FATAL: failed to fetch asset for bastion:
    devopsdefender/dd: asset bastion.x86_64 not found
  Kernel panic - not syncing: Attempted to kill init!

Rename to `.tmpl` so `bake` substitutes variables (same pattern as
`apps/dd-agent/workload.json.tmpl`), and add `"tag": "${DD_RELEASE_TAG}"`
so every environment pulls the binary matching its deploy (PR preview
tag, `latest`, or a manual rollback tag).
@github-actions
Copy link
Copy Markdown

DD preview ready

URL: https://pr-164.devopsdefender.com

Browser login: visit https://pr-164.devopsdefender.com — Cloudflare Access routes you
through GitHub OAuth. Membership (public) in the DD GitHub
org grants access; the DD_ACCESS_ADMIN_EMAIL is the
break-glass fallback.

Machine-to-machine: GitHub Actions workflows in the
DD_OWNER org pass their per-job OIDC JWT as
Authorization: Bearer … (audience dd-agent).

Register endpoint for a local agent: https://pr-164.devopsdefender.com/register
(CF-Access-bypassed; authenticated by ITA attestation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant