Skip to content
Open
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
148 changes: 146 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
[workspace]
members = [
"apps/soma",
"apps/synapse",
"crates/integrations/gotify",
"crates/integrations/unifi",
"crates/shared/auth",
Expand Down
9 changes: 8 additions & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,18 @@ synapse-canonical-read-check:
cargo test -p soma-infra --all-features
cargo test -p synapse-application

# Validate canonical reads plus lifecycle, artifact, build, and replacement mutations
# Validate all 35 canonical reads and all 21 canonical mutations
synapse-mutation-check:
cargo test -p soma-infra --all-features
cargo test -p synapse-application

# Validate the standalone Synapse CLI, REST, HTTP MCP, and stdio MCP product
synapse-standalone-check:
cargo test -p synapse --all-targets
cargo clippy -p synapse --all-targets -- -D warnings
RUSTDOCFLAGS="-D warnings" cargo doc -p synapse --no-deps
cargo run -p synapse -- --compact operations > /dev/null

# Validate neutral fleet contracts and all optional drivers
fleet-check:
cargo test -p soma-fleet --all-features
Expand Down
52 changes: 52 additions & 0 deletions apps/synapse/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[package]
name = "synapse"
version = "0.7.0"
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
description = "Standalone canonical infrastructure operations runtime"
homepage.workspace = true
license.workspace = true
repository.workspace = true
publish = false
autobins = false

[package.metadata.soma-architecture]
layer = "app"

[lib]
name = "synapse"

[[bin]]
name = "synapse"
path = "src/bin/synapse.rs"

[dependencies]
anyhow = "1"
async-trait = "0.1"
axum = "0.8"
clap = { version = "4", features = ["derive", "env"] }
dirs = "6"
rmcp = { workspace = true, features = ["server", "transport-io", "transport-streamable-http-server", "elicitation"] }
schemars = "1.2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
synapse-application = { workspace = true }
soma-fleet = { workspace = true, features = ["openssh-driver", "process-driver"] }
soma-infra = { workspace = true, features = ["bollard-driver", "linux-filesystem", "process-driver", "remote-bollard"] }
soma-ops = { workspace = true }
thiserror = "2"
tokio = { version = "1", features = ["full"] }
tokio-util = { version = "0.7", default-features = false }
toml = "1"
tower = { version = "0.5", features = ["util"] }
tower-http = { version = "0.7", features = ["auth", "cors", "trace"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }

[dev-dependencies]
rmcp = { workspace = true, features = ["client", "transport-child-process"] }
tempfile = "3"

[lints]
workspace = true
66 changes: 66 additions & 0 deletions apps/synapse/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Synapse

Standalone Synapse is the native product adapter over Soma's canonical operations engine. It links `synapse-application`, `soma-ops`, `soma-fleet`, and `soma-infra` directly and has no dependency on `crates/synapse/import`.

## Coverage

- 35 read operations
- 21 mutation operations
- 59 total canonical operations
- CLI, REST, HTTP MCP, and stdio MCP
- optional historical `flux` and `scout` request aliases
- canonical JSON results only

## Run

```bash
cargo run -p synapse -- operations
cargo run -p synapse -- run product.help --params '{}'
cargo run -p synapse -- plan container.restart \
--params '{"host":"local","container_id":"api"}'
cargo run -p synapse -- run container.restart --yes \
--params '{"host":"local","container_id":"api"}'
cargo run -p synapse -- mcp
cargo run -p synapse -- serve
```

Configuration is loaded from `--config`, `SYNAPSE_CONFIG`, or the platform config directory at `synapse/config.toml`. If no config exists, Synapse starts with one local host confined to the current working directory.

Start from [`config.example.toml`](config.example.toml). Every filesystem, build, execution, and transfer path requires an explicit absolute root for the target host.

## HTTP

Public routes: `GET /health`, `GET /ready`, and `GET /status`.

Protected routes when `server.api_token` is set:

- `GET /operations`
- `GET /activity`
- `GET /openapi.json`
- `POST /v1/operations/<name>/plan`
- `POST /v1/operations/<name>/execute`
- `/mcp`

```bash
curl -sS -H 'Authorization: Bearer replace-with-a-long-random-token' \
-H 'Content-Type: application/json' \
http://127.0.0.1:40070/v1/operations/product.help/execute \
-d '{"parameters":{}}'
```

## Mutation authorization

Mutations always build an exact target- and topology-bound plan before authorization.

- CLI requires `--yes`.
- REST requires `confirmed: true`.
- MCP asks the client to affirm both `confirm` and `understood` through elicitation.
- `server.allow_mutations = true` enables product-level automatic confirmation and should be used only on a deliberately trusted deployment.

Authorization evidence is bound to the exact plan fingerprint and expires after `authorization_ttl_secs`. Send-state uncertainty and independent postcondition verification remain part of the canonical result.

## Verification

```bash
just synapse-standalone-check
```
Loading