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
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
[![npm](https://img.shields.io/npm/v/@bodanglin/verdict-node.svg)](https://www.npmjs.com/package/@bodanglin/verdict-node)
[![TypeScript](https://img.shields.io/badge/typescript-strict-blue.svg)](https://www.typescriptlang.org/)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![CI](https://github.com/mrnicholasbcarter-code/verdict-node/actions/workflows/ci.yml/badge.svg)](https://github.com/mrnicholasbcarter-code/verdict-node/actions/workflows/ci.yml)

> **OpenAI-compatible gateway adapter for Express and Next.js** — includes pre-forward execution-envelope validation.
> **Safety-checking middleware for Express and Next.js apps that call an OpenAI-compatible API.** In short: **Verdict Core decides, verdict-node enforces at the HTTP edge** — this package does not make policy decisions itself, it checks each outgoing request against a decision made elsewhere before letting it through.

---

## What is @bodanglin/verdict-node?

`@bodanglin/verdict-node` is the TypeScript gateway adapter for the **Verdict** ecosystem. Verdict Core owns policy and execution authorization; Node supplies transport middleware that can validate an `ExecutionEnvelope` before forwarding a request to an OpenAI-compatible upstream. The canonical cross-language envelope contract and Core issuance path are still being reconciled, so this alpha must not be represented as complete end-to-end policy enforcement. Node also retains local classification, discovery, ranking, and fallback behavior for compatibility routing; those heuristics are not Core authorization.
`@bodanglin/verdict-node` is a TypeScript middleware library for Express and Next.js. In plain terms, it sits in front of your app's calls to an OpenAI-compatible API and checks each request before it goes out — it does not decide what is allowed; that is the job of **Verdict Core** (the Python control plane). This package's job is to enforce Core's decision at the HTTP edge: **core decides, node enforces**.

The mechanism it enforces against is called an `ExecutionEnvelope` — plain-language: a signed record of what Core has authorized for a given request. By default, the standalone Express forwarder rejects a request outright ("fail-closed") if it arrives without a valid envelope or fails a policy check. The canonical cross-language contract for that envelope between Core (Python) and Node (TypeScript) is **still being reconciled**, so this alpha must not be represented as complete end-to-end policy enforcement yet. Node also retains its own local classification, discovery, ranking, and fallback behavior for compatibility routing; those heuristics are separate from, and not a substitute for, Core's authorization.

**Works with any OpenAI-compatible client**: Claude Code, Codex, Cursor, Cline, Hermes, Agents SDK, raw HTTP.

Expand Down Expand Up @@ -223,15 +226,15 @@ verdict-node/

## Ecosystem

| Package | Purpose |
| ----------------------------------------------------------------- | -------------------------------------- |
| [`verdict-core`](https://github.com/verdict/verdict-core) | Python control plane |
| `@bodanglin/verdict-node` | Express/Next.js middleware (this repo) |
| [`verdict-cockpit`](https://github.com/verdict/verdict-cockpit) | Next.js dashboard |
| [`verdict-risk`](https://github.com/verdict/verdict-risk) | Risk engine |
| [`verdict-edge`](https://github.com/verdict/verdict-edge) | Edge mining framework |
| [`verdict-backtest`](https://github.com/verdict/verdict-backtest) | Monte Carlo harness |
| OmniRoute | 250+ providers, 90+ free tiers |
| Package | Purpose |
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| [`verdict-core`](https://github.com/verdict/verdict-core) | Python control plane |
| `@bodanglin/verdict-node` | Express/Next.js middleware (this repo) |
| [`verdict-cockpit`](https://github.com/verdict/verdict-cockpit) | Next.js dashboard |
| [`verdict-risk`](https://github.com/verdict/verdict-risk) | Risk engine |
| [`verdict-edge`](https://github.com/verdict/verdict-edge) | Edge mining framework |
| [`verdict-backtest`](https://github.com/verdict/verdict-backtest) | Monte Carlo harness |
| OmniRoute | Per OmniRoute's own description: 250+ providers, 90+ free tiers (third-party claim, not verified by this repository) |

---

Expand Down
40 changes: 40 additions & 0 deletions specs/001-docs-pitch-accuracy/checklists/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Specification Quality Checklist: Documentation & Pitch Accuracy

**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-09-05
**Feature**: [spec.md](../spec.md)

## Content Quality

- [x] No implementation details (languages, frameworks, APIs)
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders
- [x] All mandatory sections completed

## Requirement Completeness

- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable
- [x] Success criteria are technology-agnostic (no implementation details)
- [x] All acceptance scenarios are defined
- [x] Edge cases are identified
- [x] Scope is clearly bounded
- [x] Dependencies and assumptions identified

## Feature Readiness

- [x] All functional requirements have clear acceptance criteria
- [x] User scenarios cover primary flows
- [x] Feature meets measurable outcomes defined in Success Criteria
- [x] No implementation details leak into specification

## Notes

- No clarification markers were needed; all ambiguities were resolved using
the audit's verified findings and documented as Assumptions in spec.md.
- The fail-open code defect (FR-009) is intentionally tracked as a task within
this feature's tasks.md, but is explicitly out of scope for implementation —
this is a planning/tracking inclusion, not a spec ambiguity.
- All items pass; feature is ready for `/speckit-clarify` (optional, given no
markers remain) or directly for `/speckit-plan`.
90 changes: 90 additions & 0 deletions specs/001-docs-pitch-accuracy/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Implementation Plan: Documentation & Pitch Accuracy

**Branch**: `001-docs-pitch-accuracy` | **Date**: 2026-09-05 | **Spec**: [spec.md](./spec.md)

**Input**: Feature specification from `/specs/001-docs-pitch-accuracy/spec.md`

## Summary

Rewrite the verdict-node README's opening pitch into plain, non-jargon language
while preserving three protected, already-accurate statements (Next.js
fail-open warning, envelope-reconciliation-in-progress statement, alpha
label) and the "downstream enforcement client of verdict-core" framing; hedge
the OmniRoute ecosystem-table entry as an attributed third-party claim; leave
the three verified badges untouched; and track two out-of-scope items
(missing CI badge, `createNextApiHandler` fail-open code defect) as separate,
clearly flagged tasks that this feature's implementation does not resolve.
This is a documentation-only change — no source code, dependencies, or test
framework are touched by this feature's implementable scope.

## Technical Context

**Language/Version**: N/A (Markdown documentation edit only; repository is TypeScript, but no `.ts` source is touched by this feature)

**Primary Dependencies**: N/A — no new dependencies

**Storage**: N/A

**Testing**: Editorial/diff review, not automated unit tests. Verification is a manual/scripted text-diff check confirming protected phrases are present pre- and post-edit (see quickstart.md).

**Target Platform**: GitHub-rendered Markdown (README.md), npm registry package description if applicable

**Project Type**: Library (TypeScript Express/Next.js middleware) — this feature touches only its documentation surface

**Performance Goals**: N/A

**Constraints**: Must not alter the three verified-accurate badges (npm version, TypeScript strict, MIT license) byte-for-byte; must not weaken, remove, or relocate the disclosed Next.js fail-open warning; must not touch production source files (`src/**`)

**Scale/Scope**: Single file primarily (`README.md`); optionally any doc that mirrors the same pitch/badge/ecosystem-table content

## Constitution Check

*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

Checked against `.specify/memory/constitution.md` v1.0.0:

- **Principle I (Downstream Enforcement Client, Not a Peer Product)**: PASS — FR-002 requires the "core decides, node enforces at the HTTP edge" framing be explicit in the rewritten pitch.
- **Principle II (Verifiable Claims Only)**: PASS — FR-006 and FR-011 require the OmniRoute claim be attributed as third-party; no new unverifiable claims are introduced.
- **Principle III (Disclosed Defects Stay Disclosed Until Fixed)**: PASS — FR-003, FR-009, and FR-010 explicitly forbid softening/removing the Next.js fail-open warning and forbid fixing the underlying code defect within this feature (the defect fix is a prerequisite for ever removing the warning, tracked separately).
- **Principle IV (Alpha Status Is Explicit Until Declared Otherwise)**: PASS — FR-005 requires the alpha label be retained at equal or greater prominence.

No violations identified. No entries required in Complexity Tracking.

**Post-Phase-1 re-check**: No design decisions in Phase 1 (below) introduce new constitution risk — the design is a documentation edit plus two tracked-but-deferred tasks, both of which reinforce rather than weaken Principle III. PASS (unchanged).

## Project Structure

### Documentation (this feature)

```text
specs/001-docs-pitch-accuracy/
├── plan.md # This file
├── research.md # Phase 0 output
├── quickstart.md # Phase 1 output (validation guide)
├── checklists/
│ └── requirements.md # Spec quality checklist
└── tasks.md # Phase 2 output (/speckit-tasks command)
```

No `data-model.md` or `contracts/` are produced: this feature has no new data
entities, persistence, or external interface contracts — it edits static
Markdown content in an existing file.

### Source Code (repository root)

```text
README.md # primary edit target (pitch, ecosystem table, badges)
.github/workflows/ci.yml # referenced only (CI badge task), not modified by this feature's implementation
src/middleware/next.ts (or similar) # referenced only for the fail-open defect tracking task; NOT edited by this feature
```

**Structure Decision**: Single-file documentation edit against the existing
repository root (`README.md`). No new directories, packages, or modules are
created. The two out-of-scope tracked tasks (CI badge, fail-open defect)
reference existing files (`.github/workflows/ci.yml`, the Next.js handler
source) for identification purposes only; this feature's tasks.md will mark
those tasks explicitly non-blocking/out-of-scope-for-implementation.

## Complexity Tracking

No constitution violations identified; this section is intentionally empty.
75 changes: 75 additions & 0 deletions specs/001-docs-pitch-accuracy/quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Quickstart: Validating Documentation & Pitch Accuracy

This is a documentation-only feature. Validation is editorial/diff-based, not
a runtime test suite. Use this guide to confirm the change meets the spec's
Success Criteria (SC-001 through SC-006) before merge.

## Prerequisites

- A checkout of this repository on the feature branch (`001-docs-pitch-accuracy` or equivalent).
- The pre-edit `README.md` available for comparison (e.g., via `git show main:README.md` or the original audit snapshot).

## Step 1 — Capture the baseline

```bash
git show HEAD:README.md > /tmp/readme-before.md
```

## Step 2 — Apply the documentation edits

(Performed during `/speckit-implement` — not part of this planning pass.)
Edits touch only:
- The opening pitch/title/tagline block.
- The OmniRoute row in the ecosystem/comparison table.
- Optionally, the badge row (CI badge addition only — the three existing badges must not change).

## Step 3 — Verify protected statements survive (SC-002)

Confirm the following phrases (or clear paraphrases carrying the same claim)
are present in the edited `README.md`:

```bash
grep -i "fail-closed\|fail-open" README.md # Next.js warning must still appear
grep -i "reconcil" README.md # envelope contract statement must still appear
grep -i "alpha" README.md # alpha status label must still appear
```

Each command MUST return at least one match. If any returns no match, the
edit has removed a protected statement and must be reverted/fixed before
proceeding.

## Step 4 — Verify badges are unchanged (SC-004)

```bash
diff <(grep -i "npm/v/\|badge.*typescript\|badge.*license" /tmp/readme-before.md) \
<(grep -i "npm/v/\|badge.*typescript\|badge.*license" README.md)
```

Expected: no diff output (the three badge lines are identical).

## Step 5 — Verify the OmniRoute attribution (SC-003)

Manually read the OmniRoute row in the ecosystem table and confirm a second
reviewer agrees the figures are unambiguously attributed to OmniRoute itself
(e.g., "per OmniRoute," "OmniRoute states," a footnote citing OmniRoute),
not stated as this repository's own verified fact.

## Step 6 — Verify plain-language comprehension (SC-001)

Ask a reviewer unfamiliar with terms like "ExecutionEnvelope" or
"fail-closed" to read only the rewritten pitch and restate, in their own
words, what verdict-node does and how it relates to verdict-core. Success:
they can do so without needing the jargon defined first.

## Step 7 — Verify no source code was touched (SC-006)

```bash
git diff --name-only HEAD | grep -E '^src/' && echo "FAIL: source files touched" || echo "PASS: no source files touched"
```

## Optional automated check

For a lightweight repeatable regression check on the three protected
phrases, consider adding a CI step running the `grep` checks from Step 3 —
noted here as an optional follow-up, not a requirement of this feature
(see research.md, Decision: Verification method is text/diff review).
46 changes: 46 additions & 0 deletions specs/001-docs-pitch-accuracy/research.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Phase 0 Research: Documentation & Pitch Accuracy

No `NEEDS CLARIFICATION` markers remain in the Technical Context — this is a
documentation-only feature with no unresolved technology choices. This file
records the small number of judgment calls made while scoping the plan.

## Decision: Treat this as a documentation-only feature (no code changes)

- **Decision**: Implementation scope is limited to Markdown documentation
(primarily `README.md`); the `createNextApiHandler` fail-open defect is
tracked as a task but explicitly excluded from this feature's
implementable work.
- **Rationale**: The originating audit already separated the two concerns
(docs accuracy vs. a real code defect); conflating them would let a
docs-cleanup pass silently absorb or bury a safety-relevant bug fix, which
the project constitution (Principle III) forbids.
- **Alternatives considered**: Bundling the code fix into this feature was
considered and rejected — it would inflate scope, mix a safety-critical
code change into a low-risk documentation PR, and make the docs change
harder to review and revert independently.

## Decision: Verification method is text/diff review, not unit tests

- **Decision**: "Tests" for this feature are a before/after text comparison
confirming protected phrases (fail-open warning, reconciliation statement,
alpha label, three badges) are present and unweakened, plus a manual
read-through for the OmniRoute attribution clarity.
- **Rationale**: There is no runtime behavior to unit-test; the deliverable
is static prose. A diff-based check is the most direct, low-overhead way
to enforce the "must not remove/soften" constraints from the spec.
- **Alternatives considered**: A markdown-linting script that greps for the
exact protected strings was considered as a stronger automated gate;
documented as an optional follow-up in quickstart.md rather than a hard
requirement, since exact-string matching would break on any legitimate
copy-edit and create false failures.

## Decision: "Related docs" scope boundary

- **Decision**: In-scope docs are `README.md` and any file it directly
duplicates content from (pitch, badges, ecosystem table); out of scope is
any unrelated documentation that doesn't repeat these specific claims.
- **Rationale**: Keeps the feature bounded and matches the audit's findings,
which were all located in `README.md`.
- **Alternatives considered**: A repo-wide documentation sweep was
considered and rejected as out of scope — no audit evidence indicates the
same inaccuracies exist elsewhere.
Loading