98 lines
4.2 KiB
Markdown
98 lines
4.2 KiB
Markdown
|
|
# Path B — `kind = 'Sidecar` (ADR-030 mechanism #6)
|
||
|
|
|
||
|
|
Phase A — implementable today. The main ontoref daemon proxies
|
||
|
|
dispatch over HTTP to a per-project sidecar process. Each sidecar can
|
||
|
|
ship its own deploy cadence and signing key while sharing a Rust
|
||
|
|
library with sibling instances.
|
||
|
|
|
||
|
|
Canonical use case: shared-domain (`provisioning`) + Level-3 instances
|
||
|
|
(`libre-daoshi`, `libre-wuji`, `libre-forge`) — see
|
||
|
|
[`reflection/qa.ncl::ontoref-catalog-discovery-shared-domain`](../../.ontoref/reflection/qa.ncl).
|
||
|
|
|
||
|
|
## Files
|
||
|
|
|
||
|
|
| File | Purpose |
|
||
|
|
| --- | --- |
|
||
|
|
| [`catalog/send_email_notification.ncl`](catalog/send_email_notification.ncl) | Catalog declaration with `kind = 'Sidecar` |
|
||
|
|
| [`sidecar/Cargo.toml`](sidecar/Cargo.toml) | Standalone Cargo manifest (own workspace) |
|
||
|
|
| [`sidecar/src/main.rs`](sidecar/src/main.rs) | Minimal axum server on `:7902` — validates inputs, mock-dispatches email, returns `DispatchResponse`-shaped JSON |
|
||
|
|
| [`config-snippet.ncl`](config-snippet.ncl) | `ops.sidecar_url = "http://127.0.0.1:7902"` snippet for `.ontoref/config.ncl` |
|
||
|
|
|
||
|
|
## How to run
|
||
|
|
|
||
|
|
1. Build and start the sidecar (standalone — not part of ontoref's
|
||
|
|
workspace):
|
||
|
|
|
||
|
|
cd examples/catalog-extension/02-sidecar/sidecar
|
||
|
|
cargo run
|
||
|
|
|
||
|
|
You should see:
|
||
|
|
|
||
|
|
INFO addr=127.0.0.1:7902 example-mail-sidecar listening
|
||
|
|
|
||
|
|
2. Test the sidecar directly (bypass the main daemon proxy):
|
||
|
|
|
||
|
|
curl -s -X POST http://127.0.0.1:7902/ops/send_email_notification \
|
||
|
|
-H 'Content-Type: application/json' \
|
||
|
|
-d '{"inputs":{"recipient":"jpl@jesusperez.pro","subject":"hi","body":"hello","template":"plain"}}' \
|
||
|
|
| jq .
|
||
|
|
|
||
|
|
Expected response (message_id varies):
|
||
|
|
|
||
|
|
{
|
||
|
|
"status": "queued",
|
||
|
|
"message_id": "msg-19a3c8...-jpl",
|
||
|
|
"payload": {
|
||
|
|
"recipient": "jpl@jesusperez.pro",
|
||
|
|
"subject": "hi",
|
||
|
|
"template": "plain",
|
||
|
|
"bytes": 5
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
3. To dispatch via the main daemon (once the Phase A proxy handler
|
||
|
|
lands in `crates/ontoref-daemon/src/api.rs`):
|
||
|
|
|
||
|
|
curl -X POST 'http://127.0.0.1:7891/ops/send_email_notification?project=<your-project>' \
|
||
|
|
-H "Authorization: Bearer $ONTOREF_TOKEN" \
|
||
|
|
-d '{"recipient":"jpl@jesusperez.pro","subject":"hi","body":"hello","template":"plain"}'
|
||
|
|
|
||
|
|
The daemon looks up `sidecar_url` for the project, proxies the
|
||
|
|
request to `http://127.0.0.1:7902/ops/send_email_notification`,
|
||
|
|
signs the response envelope as the witness, returns the
|
||
|
|
`DispatchResponse` to the caller.
|
||
|
|
|
||
|
|
## Key properties
|
||
|
|
|
||
|
|
- **`evaluate_ondaod` is mandatory in `constraints.pre`** — ADR-034
|
||
|
|
Hard constraint. The host runtime invokes ondaod-discipline before
|
||
|
|
proxying to the sidecar; the sidecar itself cannot satisfy it.
|
||
|
|
- **Witness honesty** — `payload_kind = "sidecar_response_envelope"`.
|
||
|
|
The daemon's signature attests it faithfully forwarded the sidecar's
|
||
|
|
reported effect; it does NOT claim to attest the sidecar's internal
|
||
|
|
computation (HTTP boundary is opaque).
|
||
|
|
- **Per-instance signing key** — each instance's sidecar can be
|
||
|
|
configured with its own actor id; the cryptographic blast radius
|
||
|
|
stays per-instance.
|
||
|
|
- **No wasmtime dependency** — Sidecar runtime is HTTP + axum + tokio
|
||
|
|
in the sidecar process; the main daemon adds only a ~80-LOC
|
||
|
|
reqwest-based proxy handler. Honours
|
||
|
|
`protocol-not-runtime` axiom (invariant=true).
|
||
|
|
|
||
|
|
## When NOT to use
|
||
|
|
|
||
|
|
- The op is part of the ontoref piloto self-host → use
|
||
|
|
[Path A `'Rust`](../01-rust/) (zero IPC overhead, full type safety).
|
||
|
|
- You need cross-instance op dispatch with witness chaining → ADR-030
|
||
|
|
T3 trigger, leans toward Phase B WASM.
|
||
|
|
- You need to author the op in a non-Rust language → Path B works
|
||
|
|
(sidecar can be any language as long as it speaks the HTTP contract)
|
||
|
|
but consider whether toolchain divergence justifies a Phase B
|
||
|
|
spike per ADR-030 T4.
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- [ADR-030 mechanism #6 — SidecarProcessWithSharedDomainLibrary](../../../.ontoref/adrs/adr-030-catalog-discovery-cross-project.ncl)
|
||
|
|
- [`reflection/qa.ncl::ontoref-catalog-discovery-shared-domain`](../../../.ontoref/reflection/qa.ncl)
|
||
|
|
- [ADR-018 — Delegate / Override / Compose semantics](../../../.ontoref/adrs/adr-018-level-hierarchy-mode-resolution-strategy.ncl)
|