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
35 changes: 35 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Router -> Runtime HTTP base (required for HTTP runtime mode)
RUNTIME_URL=https://runtime.commandlayer.org

# Port to listen on (default: 8080)
PORT=8080

# Where to write NDJSON run logs
RUN_LOG_DIR=run-logs

# Receipt signing private key (one of these must be set for signing)
# RECEIPT_SIGNING_PRIVATE_KEY_PEM=-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----
# RECEIPT_SIGNING_PRIVATE_KEY_B64=<base64-encoded raw private key bytes>

# ENS resolution for ?ens=1 verify mode
ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/your-key
VERIFIER_ENS_NAME=runtime.commandlayer.eth
ENS_PUBKEY_TEXT_KEY=cl.receipt.pubkey.pem

# Schema host (default: https://www.commandlayer.org)
SCHEMA_HOST=https://www.commandlayer.org

# Schema verification mode:
# false (default) = fetch+compile on demand with cache
# true = only use pre-warmed validators; return 202 if not warmed
VERIFY_SCHEMA_CACHED_ONLY=false

# Enable /debug/* endpoints (unset = 404)
# ENABLE_DEBUG=1
# DEBUG_TOKEN=changeme

# Idempotency cache TTL in ms (default: 60000)
IDEMPOTENCY_TTL_MS=60000

# SSRF: comma-separated additional allowed hostnames for fetch verb
# ALLOW_FETCH_HOSTS=trusted-api.example.com
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: ci

on:
push:
branches: ["**"]
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"

- name: Install dependencies
run: npm ci

- name: Type check
run: npm run lint

- name: Build
run: npm run build

- name: Test
run: npm test
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Changelog

## 0.1.0

Initial implementation:

- `POST /run/v1.0.0` with explicit plan and scored router modes
- 10 Commons verbs: fetch, describe, format, clean, parse, summarize, convert, explain, analyze, classify
- Deterministic score function (no LLM): relevance + need_bonus + novelty + cost_penalty + risk_penalty
- Prerequisite graph: fetch→clean→summarize→classify→parse→analyze→format (state-gated)
- Schema-shaped request builders per verb (fetch special: x402+source only)
- Append-only state model: `RunState` with artifacts, trace, decisions
- Ed25519 + SHA-256 + json.sorted_keys.v1 receipt signing/verification
- ENS TXT pubkey resolution for `runtime.commandlayer.eth` (`?ens=1`)
- Schema validation via AJV compileAsync with background warm queue (`/debug/prewarm → 202`)
- `/verify?schema=1`: cached-only mode returns 202 + retry_after_ms when not warmed
- SSRF guard for fetch: blocks private IPs, localhost, IPv6, metadata addresses
- Idempotency cache: SHA-256 key derivation from stable stringify; TTL configurable
- NDJSON replay logs per run in `RUN_LOG_DIR`; `/replay/:run_id` endpoint
- HTTP delegate mode: `RUNTIME_URL` → `RuntimeClient` per step
- Local reference handlers (demo/test; no HTTP)
- CLI: `cl-router run --goal ... --content/source/plan`
- Debug endpoints gated by `ENABLE_DEBUG` env
- ENS anchors embedded as constants: `ENS_RUNTIME_SIGNER`, `ENS_CLEANAGENT_EXAMPLE`
- Tests: scoring, prereqs, requestBuilders, idempotency, engine
- CI: lint + build + test
- Docs: SPEC, API, CONTRACTS, INTEGRATION_RUNTIME, INTEGRATION_SITE, EXAMPLES
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) CommandLayer

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
164 changes: 163 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,163 @@
# router
# CommandLayer Router

Deterministic router runtime for the **CommandLayer Protocol Commons** (10 universal verbs).

## What it does

- `POST /run/v1.0.0` — executes Commons verbs via:
- **explicit plan mode** (caller supplies ordered steps with conditions)
- **scored mode** (deterministic scoring function; **no LLM**)
- Builds **schema-shaped** Commons requests (`fetch` is special)
- Produces **signed receipts per step** (Ed25519 + SHA-256 + sorted keys v1)
- `POST /verify` — verifies receipts (optional ENS pubkey + schema validation)
- AJV schema warm queue (non-blocking)
- Idempotency cache (SHA-256 key derivation)
- NDJSON replay logs per run
- SSRF guard for fetch verb
- CLI: `cl-router`

## Commons Verbs (10 Universal)

```
fetch describe format clean parse
summarize convert explain analyze classify
```

## Quickstart

```bash
npm install
npm run build
npm test
npm start
```

Server starts on `http://localhost:8080`.

## CLI

```bash
# Scored mode
node dist/cli/cl-router.js run --goal "summarize this" --content "Hello world"

# With URL source
node dist/cli/cl-router.js run --goal "fetch and summarize" --source https://example.com

# Explicit plan from JSON file
node dist/cli/cl-router.js run --plan my-plan.json
```

## HTTP Delegate Mode

Set `RUNTIME_URL` to delegate step execution to the CommandLayer runtime:

```bash
RUNTIME_URL=https://runtime.commandlayer.org npm start
```

Without `RUNTIME_URL`, the router uses local reference handlers (demo/test).

## Endpoints

| Method | Path | Description |
|---|---|---|
| `GET` | `/health` | Health check |
| `POST` | `/run/v1.0.0` | Execute a run |
| `POST` | `/verify` | Verify a signed receipt |
| `GET` | `/replay/:run_id` | Retrieve run event log |
| `POST` | `/debug/prewarm` | Warm schema validators (requires ENABLE_DEBUG) |
| `GET` | `/debug/validators` | Show AJV cache state (requires ENABLE_DEBUG) |

## ENS Anchors (Source of Truth)

### `runtime.commandlayer.eth` — Receipt Signer Identity

```
cl.receipt.pubkey.pem = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA7Vkkmt6R02Iltp/+i3D5mraZyvLjfuTSVB33KwfzQC8=\n-----END PUBLIC KEY-----"
cl.sig.kid = "v1"
cl.sig.pub = "ed25519:CEHI9g4v8qMx8TLlbLVW7RtiCmzRF7U7gpkrp0iB/a0="
cl.sig.canonical = "json.sorted_keys.v1"
cl.receipt.signer = "runtime.commandlayer.eth"
```

### `cleanagent.eth` — Canonical Commons Agent TXT Shape

```
cl.verb = "clean"
cl.version = "1.0.0"
cl.class = "commons"
cl.entry = "x402://cleanagent.eth/clean/v1.0.0"
cl.receipt.signer = "runtime.commandlayer.eth"
eth = "0xED976cA9036bC2d4E25BA8219faDA1Be503a09C7"
```

## Environment Variables

```bash
PORT=8080
RUNTIME_URL=https://runtime.commandlayer.org # HTTP delegate mode
RUN_LOG_DIR=run-logs # NDJSON replay log dir
RECEIPT_SIGNING_PRIVATE_KEY_PEM=... # Ed25519 private key PEM
ETH_RPC_URL=... # For ENS resolution (?ens=1)
VERIFIER_ENS_NAME=runtime.commandlayer.eth
SCHEMA_HOST=https://www.commandlayer.org
VERIFY_SCHEMA_CACHED_ONLY=false
ENABLE_DEBUG=1 # Enable /debug/* endpoints
DEBUG_TOKEN=changeme
IDEMPOTENCY_TTL_MS=60000
ALLOW_FETCH_HOSTS=trusted-api.example.com # SSRF bypass list
```

See `.env.example` for full reference.

## Docs

- [docs/SPEC.md](docs/SPEC.md) — Full `/run/v1.0.0` specification
- [docs/API.md](docs/API.md) — API reference
- [docs/CONTRACTS.md](docs/CONTRACTS.md) — RunRequest/RunResponse + receipt expectations
- [docs/INTEGRATION_RUNTIME.md](docs/INTEGRATION_RUNTIME.md) — Runtime integration guide
- [docs/INTEGRATION_SITE.md](docs/INTEGRATION_SITE.md) — Site docs updates
- [docs/EXAMPLES.md](docs/EXAMPLES.md) — Usage examples

## Architecture

```
src/
server.ts Express server + route registration
index.ts Public API exports
router/
commonsVerbs.ts 10-verb list
policy.ts allow/deny verb policy
prereqs.ts Prerequisite graph (deterministic)
scoring.ts Score function + verb selector
state.ts RunState helpers (append-only)
requestBuilders.ts Schema-shaped request builders per verb
applyReceipt.ts Receipt → artifact mapping
stop.ts Global stop condition
engine.ts Main run loop (explicit + scored)
schemas/
urls.ts Schema URL builders
ajv.ts AJV instance + validator cache
warm.ts Background warm queue
receipts/
sign.ts Ed25519 sign + verify
verify.ts /verify endpoint handler
ens.ts ENS TXT pubkey resolver
security/
ssrf.ts SSRF guard for fetch
logging/
replay.ts NDJSON event logger
idempotency/
cache.ts In-memory idempotency cache
client/
runtimeClient.ts HTTP client for runtime delegate
cli/
cl-router.ts CLI entrypoint
types/
run.ts RunRequest/RunResponse/RunState types
commons.ts CommonsVerb type + ENS anchor constants
```

## License

MIT
Loading
Loading