Skip to content
Merged
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
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Abbenay produces two packages from a single source tree:
- **MCP aggregation**: Connect to external MCP servers, expose daemon as MCP server
- **Dynamic model discovery**: Fetches available models from provider APIs
- **Single Executable Application (SEA)**: Self-contained binary, no Node.js install required
- **Secure-by-default daemon**: HTTP on `127.0.0.1` with auth + CORS allowlist; gRPC TLS required off-loopback — see [SECURITY.md](docs/SECURITY.md)

## Why "Abbenay"?

Expand Down Expand Up @@ -140,11 +141,14 @@ curl -H "Authorization: Bearer $ABBENAY_API_TOKEN" \

Works with Cursor, Continue, aider, and any `openai` SDK script (use the same
token as the client API key). The HTTP server binds to `127.0.0.1` by default;
use `--host 0.0.0.0` only when you intentionally expose it.
use `--host 0.0.0.0` only when you intentionally expose it. gRPC TCP on
non-loopback addresses requires `--grpc-tls` (or explicit `--insecure`).

> **WARNING:** Auth is on by default. `ABBENAY_HTTP_AUTH=0` disables it on any
> bind (including `--host 0.0.0.0`) — for example a cluster-internal pod, or
> when a reverse proxy already authenticates callers. See
> when a reverse proxy already authenticates callers. Air-gap or offline use
> with local models reduces *egress*, but **network isolation alone does not
> secure Abbenay**. See [Security & air-gap](docs/SECURITY.md) and
> [Configuration](docs/CONFIGURATION.md#http-api-security-server).

### Using the core library
Expand Down Expand Up @@ -289,6 +293,7 @@ abbenay/
## Documentation

- [Getting Started](docs/GETTING_STARTED.md)
- [Security, Privacy & Air-Gap](docs/SECURITY.md) — defaults, residual risks, operator checklist
- [Core Library (API Reference)](docs/CORE.md)
- [Architecture](docs/ARCHITECTURE.md)
- [Configuration](docs/CONFIGURATION.md)
Expand Down
17 changes: 13 additions & 4 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The core TypeScript/Node.js process that runs as a background daemon.

The web dashboard runs inside the daemon process via Express:

- **Port**: `localhost:8787` (configurable)
- **Bind / port**: `127.0.0.1:8787` by default (configurable; auth required)
- **Static assets**: Served from `packages/daemon/static/`
- **API routes**: `/api/*` -> Direct calls to `DaemonState` (no gRPC in the loop)
- **Chat SSE**: `POST /api/chat` -> Streaming responses via Server-Sent Events
Expand Down Expand Up @@ -491,7 +491,16 @@ internal MCP tool for cross-session retrieval.
## Security

- **Secrets**: Stored in system keychain via keytar when available; never in config files
- **Socket**: Unix socket (or named pipe) with user-only permissions
- **Web dashboard**: Listens on localhost only
- **No remote access**: Daemon designed for local use only
- **Socket**: Unix socket (or named pipe) with user-only permissions (local IPC)
- **Web dashboard / HTTP API**: Binds to `127.0.0.1` by default; Bearer (or
cookie + CSRF) auth required; CORS allowlist only (never `*`) — DR-030
- **gRPC TCP**: Loopback plaintext OK for local DX; non-loopback requires
`--grpc-tls` or explicit `--insecure` — DR-029. Empty `consumers` refused
off-loopback unless `--allow-open-auth` / `--insecure` — DR-037
- **Air-gap / privacy**: Local and on-prem engines can keep prompts off the
public internet, but **network isolation alone does not secure the daemon**.
See [SECURITY.md](./SECURITY.md).
- **Config files**: Created with mode `0o600` (user read/write only)

Intentional exposure (containers, LAN) is opt-in via `--host` / image CMD —
see [CONTAINER.md](./CONTAINER.md) and [SECURITY.md](./SECURITY.md).
4 changes: 4 additions & 0 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ MCP endpoint (`/mcp`) require authentication by default. MCP tool calls also
honor `tool_policy` (same approval path as chat — see [Tool policy](#tool-policy)
below).

For air-gap / privacy claims vs real defaults, see
[SECURITY.md](./SECURITY.md). **Network isolation alone does not secure
Abbenay.**

| Setting / env | Purpose | Default |
|---------------|---------|---------|
| `ABBENAY_API_TOKEN` or `server.api_token` / `server.api_token_env` | Bearer token for all HTTP routes | Auto-generated and stored as `http-api-token` in the config directory |
Expand Down
5 changes: 5 additions & 0 deletions docs/CONTAINER.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,11 @@ spec:

## Security: HTTP bind and authentication

> Workstation CLI defaults bind HTTP to `127.0.0.1` with auth on. The
> **container image CMD** intentionally uses `--host 0.0.0.0` so published
> ports work — that is opt-in exposure, not “air-gap security.” See
> [SECURITY.md](./SECURITY.md).

| Flag | Default | Effect |
|------|---------|--------|
| `--host` / `ABBENAY_HTTP_HOST` / `server.host` | `127.0.0.1` | HTTP bind (dashboard, `/api/*`, `/v1/*`, `/mcp`) |
Expand Down
5 changes: 4 additions & 1 deletion docs/GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,9 @@ same token as the API key.
> logs a warning. Use auth-off when something else already protects the API
> (for example a production pod on a private cluster network, or a reverse
> proxy / gateway that authenticates callers). Otherwise keep auth on and
> use `ABBENAY_API_TOKEN`.
> use `ABBENAY_API_TOKEN`. Defaults bind HTTP to `127.0.0.1` with CORS
> allowlisted — see [SECURITY.md](SECURITY.md). Offline / air-gap use with
> local models does **not** replace these controls.

### With the OpenAI Python SDK

Expand Down Expand Up @@ -394,6 +396,7 @@ aby list-engines

## Next steps

- [Security, Privacy & Air-Gap](SECURITY.md) — defaults vs air-gap claims
- [Configuration Reference](CONFIGURATION.md) — all config options
- [Core Library API](CORE.md) — use `@abbenay/core` in your own apps
- [Architecture](ARCHITECTURE.md) — how the system fits together
Expand Down
8 changes: 6 additions & 2 deletions docs/LANDSCAPE.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,14 @@ aggregation, and a web dashboard.
**Strengths:** no infrastructure to deploy, works offline with local
models, secrets stay on the developer's machine, same core powers CLI /
daemon / extension / web, in-process tool execution with approval
policies.
policies. Secure-by-default HTTP (localhost bind, auth, CORS allowlist)
and fail-closed gRPC TLS off-loopback — see [SECURITY.md](./SECURITY.md).

**Trade-offs:** not designed for team-wide centralized control, no
built-in cost tracking or billing, earlier in development.
built-in cost tracking or billing, earlier in development. Offline /
air-gap routing to local models reduces public-cloud egress; it does
**not** by itself authenticate callers or replace daemon security
controls.

---

Expand Down
15 changes: 14 additions & 1 deletion docs/PRODUCT_OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Status:** MVP Complete
**Version:** 0.0.0-dev
**Last Updated:** March 2026
**Last Updated:** July 2026

---

Expand Down Expand Up @@ -252,6 +252,19 @@ providers:

---

## Security and air-gap posture

Abbenay supports **local and on-prem engines** (Ollama, Red Hat AI, LM Studio,
custom OpenAI-compatible endpoints) so operators can keep prompts inside their
network. That is a routing choice — not a security boundary by itself.

Defaults: HTTP on `127.0.0.1` with auth and CORS allowlist; gRPC TLS required
off-loopback. Abbenay does **not** ship network-isolation controls (firewall /
offline enforcement); operators own that layer. **Network isolation alone does
not secure Abbenay.** See [SECURITY.md](./SECURITY.md).

---

## Out of Scope

| Item | Notes |
Expand Down
8 changes: 7 additions & 1 deletion docs/REDHAT_AI.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ an OpenAI-compatible REST API:
Both speak the same protocol, so Abbenay routes them through
`@ai-sdk/openai-compatible` — no additional SDK packages are required.

Local Inference Server deployments support air-gapped / offline inference
(prompts stay on your network). That does **not** mean network isolation
secures the daemon — see [SECURITY.md](./SECURITY.md).

---

## Profile A — Inference Server
Expand Down Expand Up @@ -189,9 +193,10 @@ providers:
| 5 | Model discovery (CLI) | `aby list-models --discover redhat` |
| 6 | Model discovery (web) | Add Provider wizard → select `redhat` |
| 7 | Chat completions | `aby chat -m redhat-inference/<model>` |
| 8 | Streaming | `curl http://localhost:8787/v1/chat/completions` with `"stream": true` |
| 8 | Streaming | `curl -H "Authorization: Bearer $ABBENAY_API_TOKEN" http://127.0.0.1:8787/v1/chat/completions` with `"stream": true` |
| 9 | Tool calling | `aby chat` with tools enabled (if model supports it) |
| 10 | VS Code LM API | Configure Provider → select model → chat |
| 11 | Air-gap / privacy | Use local Inference Server only; isolation alone does not secure Abbenay — see [SECURITY.md](./SECURITY.md) |

---

Expand All @@ -202,3 +207,4 @@ providers:
- [Red Hat AI Inference — Configuring API key authentication](https://docs.redhat.com/en/documentation/red_hat_ai_inference/3.4/html/getting_started/configuring-api-key-authentication_getting-started)
- [RHEL AI 3.4 — Getting Started](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux_ai/3.4/html-single/getting_started/getting_started)
- [Abbenay Configuration Guide](CONFIGURATION.md)
- [Security, Privacy & Air-Gap](SECURITY.md)
17 changes: 16 additions & 1 deletion docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ aider, any `openai` SDK script, etc.). See DR-020.
| `POST /v1/completions` | low — legacy |
| `POST /v1/embeddings` | low — if engines support it |
| Usage/token stats (real counts from providers) | medium |
| Bearer token auth on all HTTP routes (`server.api_token` / `ABBENAY_API_TOKEN`) | **done** |
| Bearer token auth on all HTTP routes (`server.api_token` / `ABBENAY_API_TOKEN`) | **done** (DR-030) |
| Localhost-first HTTP bind + CORS allowlist (never `*`) | **done** (DR-030) |
| gRPC TLS / fail-closed non-loopback binds | **done** (DR-029) |
| Air-gap / privacy docs aligned with defaults (finding A4) | **done** — [SECURITY.md](./SECURITY.md) |
| Rate limiting | low |

### Key files
Expand Down Expand Up @@ -260,6 +263,18 @@ by wiring to `ToolRegistry`.

---

## 8. Air-gap docs vs network exposure (A4) — done

Product copy historically overstated air-gap / privacy while defaults exposed
HTTP on all interfaces, plaintext gRPC, and wildcard CORS. Docs now state the
real defaults and that **network isolation alone does not secure Abbenay** —
see [SECURITY.md](./SECURITY.md) (DR-038), including the operator checklist
(bind, auth, CORS, TLS, consumers, MCP) and residual risks. Release notes:
`packages/vscode/CHANGELOG.md` (Unreleased → Security). Code fixes: DR-030 /
DR-029.

---

## Suggested implementation order

| Phase | Sections | Rationale | Status |
Expand Down
Loading
Loading