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
68 changes: 65 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ name: tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
# ── Python core library ───────────────────────────────────────────────
python:
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand All @@ -34,3 +33,66 @@ jobs:
run: |
python examples/run_demo.py
python examples/compute_efficiency_demo.py

# ── TypeScript hosted-MCP (Cloudflare Worker) ─────────────────────────
# iter4 H4: vitest + typecheck were previously ungated. This job runs the
# full TS suite on every push and PR. Python is also installed here so the
# cross-core parity test (tests/parity.test.ts spawns `python3`) actually
# executes instead of self-skipping.
#
# Node 22 is required: the D1 test harness (tests/helpers/d1.ts) uses the
# built-in `node:sqlite` module, which is only available on Node >= 22.5.
hosted-mcp:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node 22
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Set up Python (for the cross-core parity test)
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install Python package (parity test imports `verdigraph`)
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Install hosted-mcp dependencies
working-directory: hosted-mcp
run: npm ci

- name: Typecheck
working-directory: hosted-mcp
run: npm run typecheck

- name: Test (vitest — includes the cross-core parity test)
working-directory: hosted-mcp
run: npm test

# ── Secret scan ───────────────────────────────────────────────────────
# iter4 C2: fail the build if a live Stripe object id (or equivalent live
# credential) is committed to a tracked file. Length thresholds match real
# Stripe ids while ignoring short placeholder forms. This grep gate stands
# in for gitleaks, targeted at the exact id families this repo handles. The
# search pattern is assembled from fragments at runtime so this workflow
# file itself holds no literal id prefix.
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Scan tracked files for leaked live identifiers
run: |
set -uo pipefail
L='live_'
PATTERN="(cs_${L}|rk_${L}|sk_${L})[A-Za-z0-9]{8,}|cus_[A-Za-z0-9]{10,}|we_[A-Za-z0-9]{12,}|acct_[A-Za-z0-9]{12,}"
if git grep -nE "$PATTERN" -- . ; then
echo "::error::Live Stripe object id found in a tracked file. Scrub it — operational docs belong in the git-ignored docs/internal/."
exit 1
fi
echo "secret-scan: clean — no live identifiers in tracked files."
2 changes: 1 addition & 1 deletion ADOPTION_HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ HN Show is the single highest-leverage move. Drafts ready for all 6 channels.

### 4. (Optional) Republish under viridis-security org namespace
Your org membership is now public (I flipped it). To republish:
cd ~/Desktop/Cowork\ /axiomgraph_neurogenesis/hosted-mcp
cd path/to/verdigraph-neurogenesis/hosted-mcp
~/.local/bin/mcp-publisher logout
~/.local/bin/mcp-publisher login github # one more device-code dance
# Then edit server.json: change name to io.github.viridis-security/verdigraph-mcp
Expand Down
51 changes: 51 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [0.3.0] — unreleased (iteration 4: security & production hardening)

Hardening pass to make the paid hosted MCP (`hosted-mcp/`) safe for the Energy
AI production cutover. **Phase 0 — cutover blockers** (this entry grows as
phases 1 and 2 land).

### Security

- **Real authentication (C1).** The `/authorize` flow is now gated by GitHub
OIDC. Identity is the immutable numeric GitHub user id
(`oauth_subject = "github:" + id`, `UNIQUE`); two authorizations by the same
human resolve to the same `caller_id`, so a caller who loses a token recovers
their balance by re-authenticating. Previously every authorization minted a
fresh random subject and a brand-new empty account. New routes:
`GET /authorize` (redirect to GitHub), `GET /authorize/callback` (code
exchange + consent). New Worker secrets `GITHUB_OAUTH_CLIENT_ID` /
`GITHUB_OAUTH_CLIENT_SECRET`.
- **Operational docs purged from the public repo (C2).**
`STRIPE_GO_LIVE_STATE.md`, `STRIPE_GO_LIVE_CHECKLIST.md` and
`operator-digests/` moved to the git-ignored `docs/internal/`. Live Stripe
object ids, the Stripe account id, and absolute local filesystem paths
scrubbed from all remaining tracked files. A CI `secret-scan` job now fails
the build on any committed live identifier.

### Fixed

- **Exactly-once metering under concurrency (H1).** `meteredCall` reserves the
`usage_ledger` row on the `UNIQUE (caller_id, request_id)` index *before*
debiting, so concurrent or retried calls debit exactly once, fire exactly one
Stripe meter event, and replay the original row. Closes a TOCTOU race where
two concurrent calls sharing a `request_id` both debited.
- **Conservation cron counts all revenue streams (H2).** The monthly payout now
sums net revenue across per-call routing fees, brain unlocks, attestations
*and* marketplace sales — not routing fees alone. Marketplace conservation
ledger rows are linked to the payout that accounts for them.
- **Atomic money paths (H3).** `redeemCreditCode`, `bookPurchase`, and the
subscription-invoice credit path now commit their multi-statement mutations
as a single `D1.batch()` transaction — all-or-nothing, no partial state.

### Added

- **TypeScript CI (H4).** A `hosted-mcp` job runs `npm run typecheck` and the
full vitest suite (including the cross-core `parity.test.ts`, which now
executes against a real Python install) on every push and pull request.
- A real-SQLite D1 test harness (`hosted-mcp/tests/helpers/d1.ts`) backing the
new metering, atomic-money, conservation-cron and auth test suites.
- D1 migrations `0007_metering_settlement.sql` (usage_ledger `settlement_state`)
and `0008_conservation_multistream.sql` (link marketplace conservation rows
to payouts).

## [0.1.0] — 2026-05-17

**Permanent archive (Zenodo):**
Expand Down Expand Up @@ -54,4 +104,5 @@ plus the Phase 2 MCP runtime layer.
reconstruct evolved agents from persisted state.

[Unreleased]: https://github.com/viridis-security/verdigraph-neurogenesis/compare/v0.1.0...HEAD
[0.3.0]: https://github.com/viridis-security/verdigraph-neurogenesis/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/viridis-security/verdigraph-neurogenesis/releases/tag/v0.1.0
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
> Clone this repo, run one script, and within 60 seconds you're building **deterministic, content-addressed brain artifacts** from any agent file — Claude project export, OpenAI Assistant config, raw prompt list, or Verdigraph genome JSON. Pure Python core; zero external services required.

[![python](https://img.shields.io/badge/python-3.10+-blue?style=flat-square)](https://www.python.org)
[![tests](https://img.shields.io/badge/tests-145%20passing-success?style=flat-square)](#tests)
[![tests](https://img.shields.io/badge/tests-python%20%C2%B7%20typescript-success?style=flat-square)](#run-the-tests)
[![license](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20261687.svg)](https://doi.org/10.5281/zenodo.20261687)

Expand Down Expand Up @@ -175,12 +175,29 @@ A live reference deployment runs at [https://verdigraph.dev](https://verdigraph.

## Run the tests

Python core:

```bash
source .venv/bin/activate
pip install -e ".[dev]"
pytest -q
```

TypeScript hosted-MCP (Cloudflare Worker):

```bash
cd hosted-mcp
npm ci
npm run typecheck
npm test
```

Both suites run in CI (`.github/workflows/tests.yml`) on every push and pull
request: the Python job across 3.10 / 3.11 / 3.12, and the hosted-mcp job on
Node 22 — where the cross-core `parity.test.ts` executes against a real Python
install rather than self-skipping. A secret-scan job fails the build if a live
Stripe identifier is ever committed.

The `tests/test_brain_parity.py` suite locks the deterministic-build contract — specifically that `b'{"agent_name":"x","purpose":"y","initial_nodes":["a"],"fitness_metrics":["task_success_rate"]}'` produces `brain_id == "RMX124YY916WP0TCSEHFYX7M30"` and `content_hash == "20b9e5be0e5a0d34e564df6d0a554b1232ff9cc3ff309ab8da77a97756602c0c"`. If either side ever drifts, that test fails on the next CI run and we ship the divergence as a deliberate schema bump.

---
Expand Down
127 changes: 0 additions & 127 deletions STRIPE_GO_LIVE_CHECKLIST.md

This file was deleted.

Loading
Loading