-
Notifications
You must be signed in to change notification settings - Fork 0
Prep the repo for public visibility #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,67 +1,110 @@ | ||
| # Orca | ||
|
|
||
| Internal codename for an injection-resilient, multi-source, agentic RAG platform with | ||
| non-custodial on-chain action-prep. Boardwalk is the first tenant; the architecture is a | ||
| generic platform, not an add-on to any one app. | ||
| [](https://github.com/useboardwalk/orca/actions/workflows/ci.yml) | ||
|
|
||
| Two engines over one Neon Postgres + pgvector store: | ||
| Injection-resilient, multi-tenant agentic RAG with non-custodial on-chain action-prep. | ||
| Orca answers questions over an ingested knowledge base with cited evidence, reads live | ||
| on-chain data, and prepares — never submits — transactions the user signs in their own | ||
| wallet. [Boardwalk](https://useboardwalk.com) is the first tenant; the core is a generic | ||
| platform behind a `TenantAdapter` contract. | ||
|
|
||
| - a **Python connector framework** (`engine/`) that ingests docs and OpenAPI specs into the | ||
| store behind a uniform `Connector` contract, and | ||
| - a **TypeScript serving layer** (`apps/`, `packages/`) — a deterministic router fronting a | ||
| hand-rolled tool loop that retrieves cited evidence, reads live on-chain data, and prepares | ||
| (never submits) transactions the user signs in their own wallet. | ||
| The design premise: an LLM will eventually obey instructions planted in retrieved content, | ||
| so don't trust it not to. Safety is deterministic code, not model alignment — a taint gate | ||
| that makes obedience not matter for the action path. | ||
|
|
||
| The load-bearing safety is deterministic, not model-trust: a non-custodial wallet gate, a | ||
| taint-gated reachability check on action tools, schema-enforced field provenance, RLS tenant | ||
| isolation, and an egress allowlist. | ||
| ```mermaid | ||
| flowchart LR | ||
| W["Widget · Playground · Telegram bot"] --> R | ||
| subgraph serve ["Serving — TypeScript"] | ||
| R["Deterministic router"] --> L["Agent loop<br/>+ taint gate"] | ||
| end | ||
| subgraph ingest ["Ingestion — Python engine"] | ||
| C["Connectors<br/>docs_mdx · openapi"] | ||
| end | ||
| DB[("Neon Postgres<br/>pgvector + FTS · RLS")] | ||
| C --> DB | ||
| L -->|searchKnowledge| DB | ||
| L -->|"getLaunch — live read"| API["Boardwalk API"] | ||
| L -->|"prepare* — action tools"| TX["Unsigned tx bundle"] | ||
| TX --> U["User signs in their own wallet"] | ||
| ``` | ||
|
|
||
| ## The taint gate | ||
|
|
||
| Retrieved content carries a trust tier (tier-0 first-party docs → tier-2 uploads and | ||
| external content). The moment a tool returns content at or above the taint tier, the turn | ||
| is tainted — and while tainted, action tools are removed from the set the model is even | ||
| offered. Taint is monotonic and enforced in code the model can't argue with. A live | ||
| tainted turn: | ||
|
|
||
| ```text | ||
| router tier=tier2 reasons=["action-verb","live-lexicon"] | ||
| step 1 actionToolsActive=true → searchKnowledge → taintedAfter=true (tier-2 chunk retrieved) | ||
| step 2 actionToolsActive=false ← action tools left the model's reach | ||
| final tainted=true no signable action surfaced; answer grounded in tier-0 sources | ||
| ``` | ||
|
|
||
| Defense in depth behind the gate: spotlighted/datamarked untrusted chunks, schema-enforced | ||
| field provenance (an action address must appear verbatim in the user's typed message), | ||
| non-custodial by construction, an egress allowlist, RLS tenant isolation, and spend caps. | ||
| The full threat model, prior art (CaMeL, spotlighting), and stated boundaries — including | ||
| what is *not* defended — are in [SECURITY.md](./SECURITY.md). | ||
|
|
||
| ## Measured | ||
|
|
||
| Injection resistance, end to end against the live serving path (details and caveats in | ||
| [SECURITY.md](./SECURITY.md#evidence) and | ||
| [packages/bench/RESULTS.md](./packages/bench/RESULTS.md)): | ||
|
|
||
| | Measurement | Result | | ||
| |---|---| | ||
| | Deterministic gate floor — model *scripted to obey* the injection (`poison-asr.test.ts`, per PR) | action ASR **0** | | ||
| | [AgentDojo](https://github.com/ethz-spylab/agentdojo) attack wrappers × claim-to-attacker goal, ingested tier-2, wallet attached | action-hijack ASR **0/5**, gate engaged 5/5 | | ||
| | Live red-team (promptfoo) vs a running `/v1/chat` | **5/5** passed | | ||
| | Own-corpus PoisonedRAG-style sweep — injected *instructions*, up to 8/8 retrieval flooding | ASR **0** | | ||
| | Same sweep — injected *facts* with no true counter-source in the corpus | ASR ~1.0 — **undefended**, documented as the boundary | | ||
|
|
||
| Retrieval quality (BEIR, the production spine: hybrid RRF → voyage rerank-2.5): | ||
|
|
||
| | nDCG@10 | Orca hybrid | Orca + rerank | best published single-model first stage | | ||
| |---|---|---|---| | ||
| | SciFact | 0.802 | **0.807** | 0.784 — NV-Embed-v1 (7B) | | ||
| | FiQA-2018 | 0.565 | **0.629** | 0.631 — NV-Embed-v1 (7B) | | ||
|
|
||
| ## Layout | ||
|
|
||
| - `apps/api` — Next.js 16 route handlers (`/v1/chat`, `/v1/search`) + a `/playground` page (dev, port 3000) | ||
| - `apps/web` — Next.js admin console (better-auth): tenant settings, usage/activity, knowledge, feedback (port 3001) | ||
| - `packages/core` — router, hand-rolled loop + taint gate, tools, retrieval, guardrails | ||
| - `packages/db` — Drizzle schema (the cross-language contract), RLS policy, `withTenant`, retrieval | ||
| - `packages/tenant-boardwalk` — the Boardwalk tenant adapter (system prompt + tools) consumed via `TenantAdapter`, plus its evals | ||
| - `packages/widget` — embeddable React chat widget + the dependency-free typed stream client (`@orca/widget/stream`) | ||
| - `packages/bench` — external retrieval benchmarks (BEIR) + the injection/poison-resistance harness | ||
| - `packages/config` — shared tsconfig, the zod env contract, and the model catalog (allowlist + pricing) | ||
| - `evals/redteam` — live red-team (promptfoo + AgentDojo) against a running `/v1/chat`, with committed results | ||
| - `engine/` — Python (uv) connector framework + `docs_mdx` / `openapi` connectors | ||
| - `apps/api` — Next.js route handlers (`/v1/chat`, `/v1/search`), the Telegram bot webhook, `/playground` (port 3000) | ||
| - `apps/web` — admin console (better-auth): tenant settings, knowledge, usage, feedback (port 3001) | ||
| - `packages/core` — router, agent loop + taint gate, tools, retrieval, guardrails | ||
| - `packages/db` — Drizzle schema (the cross-language contract), RLS policy, `withTenant` | ||
| - `packages/tenant-boardwalk` — the Boardwalk tenant adapter (system prompt + tools) + its evals | ||
| - `packages/widget` — embeddable React chat widget + a dependency-free typed stream client | ||
| - `packages/bench` — BEIR benchmarks + the injection/poison-resistance harness | ||
| - `packages/config` — shared tsconfig, the zod env contract, the model catalog | ||
| - `evals/redteam` — live red-team (promptfoo + AgentDojo) with committed results | ||
| - `engine/` — Python (uv) connector framework: `docs_mdx`, `openapi` | ||
|
|
||
| ## Develop | ||
|
|
||
| Node is pinned in `.nvmrc` (22.x; the machine default may be older — don't use it). pnpm via | ||
| corepack; Python via uv. | ||
| Node 22 (`.nvmrc`), pnpm via corepack, Python via uv. | ||
|
|
||
| ```sh | ||
| pnpm install | ||
| pnpm lint:ci # biome lint + format (what CI runs) | ||
| pnpm -r typecheck && pnpm -r test # TS | ||
| pnpm -r typecheck && pnpm -r test # TS (pglite in-memory Postgres; no services needed) | ||
| node scripts/lint-tenant-access.mjs # tenant tables only reachable via withTenant | ||
| cd engine && uv run pytest # Python (incl. docs_mdx JS-parity fixtures) | ||
| cd engine && uv run pytest # Python, offline | ||
| ``` | ||
|
|
||
| Live paths need `apps/api/.env.local` + `engine/.env` (see `.env.example`): an AI Gateway key | ||
| and a Neon serving URL whose role is **non-owner + NOBYPASSRLS** (the owner role bypasses RLS). | ||
| Live paths need `apps/api/.env.local` + `engine/.env` (see [.env.example](./.env.example)): | ||
| an AI Gateway key and two Neon URLs — `DATABASE_URL` (serving) whose role must be | ||
| **non-owner + NOBYPASSRLS** (the owner role bypasses RLS, making tenant isolation a no-op), | ||
| and `ADMIN_DATABASE_URL` (owner role) used only for migrations and role setup, never for | ||
| serving. Boot fails loud if the serving role can bypass RLS. | ||
|
|
||
| ```sh | ||
| pnpm --filter @orca/db exec tsx src/migrate.ts # ADMIN_DATABASE_URL: schema + RLS + serving role | ||
| pnpm --filter @orca/db exec tsx scripts/seed-dev.mts # dev tenant + knowledge base | ||
| cd engine && uv run engine ingest docs_mdx && uv run engine ingest openapi | ||
| pnpm --filter @orca/api dev # http://localhost:3000/playground | ||
| ``` | ||
|
|
||
| ## Security & evaluation | ||
|
|
||
| The safety claim — untrusted retrieved content cannot drive a signable on-chain action — and the | ||
| evidence for it are in [SECURITY.md](./SECURITY.md): the lethal-trifecta threat model, the | ||
| deterministic taint gate, how it relates to prior art (CaMeL, spotlighting, AgentDojo), and the | ||
| boundary (fact-poisoning is not defended). | ||
|
|
||
| - `evals/redteam` — live red-team against a running `/v1/chat` (latest run: 5/5, committed `results.json`) | ||
| - `packages/bench` — external BEIR retrieval results + the injection/poison resistance numbers | ||
| - `packages/core/src/agent/poison-asr.test.ts` — the deterministic action-ASR gate floor, run per PR | ||
|
|
||
| > "Orca" is an internal codename only — rename before any public launch (collisions: orca.so | ||
| > Solana DEX, Microsoft Orca LLM, Orca Security; npm `orca` is taken). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.