From 9b54f8f2d13f1fd6e3765025c634aae6b9fb8a44 Mon Sep 17 00:00:00 2001 From: Koosha Pari Date: Thu, 25 Jun 2026 04:38:46 -0700 Subject: [PATCH] feat(v30-T1): C4 fleet inventory, contract tests CI, CycloneDX SBOM gen, lock hash check, SSOT drift cron MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Track T1 of the v30 71-pillar P2-lift plan. Five deliverables: - (a) .github/inventory/fleet.json — C4 component+container model for OmniRoute (6 containers, 5 relationships, system context) - (b) .github/workflows/contract_tests.yaml — CI workflow for boundary contract tests (triggered on PR paths: src/ open-sse/ tests/contract/) - (c) .github/workflows/sbom-gen.yaml — CycloneDX SBOM generation CI (on push to main touching package.json, weekly Monday @06:00 UTC, manual) - (d) .github/workflows/cargo-lock-hash.yaml — Weekly lock file determinism check (SHA256 hash verification, npm ci --dry-run integrity test) - (e) .github/workflows/ssot-drift-cron.yaml — Weekly SSOT drift scan (docs-sync, route-validation provider-catalog drift checks) Refs: Pillars L2, L27, L29, L30, L65 --- .github/inventory/fleet.json | 66 ++++++++++++++++++++++++++ .github/workflows/cargo-lock-hash.yaml | 42 ++++++++++++++++ .github/workflows/contract_tests.yaml | 44 +++++++++++++++++ .github/workflows/sbom-gen.yaml | 43 +++++++++++++++++ .github/workflows/ssot-drift-cron.yaml | 42 ++++++++++++++++ 5 files changed, 237 insertions(+) create mode 100644 .github/inventory/fleet.json create mode 100644 .github/workflows/cargo-lock-hash.yaml create mode 100644 .github/workflows/contract_tests.yaml create mode 100644 .github/workflows/sbom-gen.yaml create mode 100644 .github/workflows/ssot-drift-cron.yaml diff --git a/.github/inventory/fleet.json b/.github/inventory/fleet.json new file mode 100644 index 00000000000..4b1e31d11bf --- /dev/null +++ b/.github/inventory/fleet.json @@ -0,0 +1,66 @@ +{ + "$schema": "https://raw.githubusercontent.com/kooshapari/phenotype-registry/main/schemas/c4-fleet.schema.json", + "version": "1.0", + "generated": "2026-06-27", + "pillar_target": 3.55, + "systems": { + "omniroute": { + "name": "OmniRoute", + "description": "Unified AI proxy/router — route any LLM through one endpoint. 232 providers, 15 routing strategies, 87 MCP tools, 42 i18n locales.", + "type": "system", + "repo": "KooshaPari/OmniRoute", + "tags": ["ai-proxy", "router", "llm-gateway"], + "containers": [ + { + "name": "Next.js App Router", + "type": "container", + "technology": "Next.js 16 / TypeScript 6 / Tailwind CSS v4", + "description": "API routes (v1 chat, embeddings, images, audio, video, search, rerank), dashboard UI, SSE streaming, i18n (42 locales)", + "responsibilities": ["HTTP API surface", "Dashboard rendering", "Authentication", "CORS enforcement"] + }, + { + "name": "SQLite Database", + "type": "container", + "technology": "better-sqlite3 / WAL mode", + "description": "Persistence layer with 83 domain modules, 97 schema migrations, 17 base tables. Encryption at rest for sensitive fields.", + "responsibilities": ["Provider/model catalog storage", "Usage/billing tracking", "Combo routing config", "API key management", "MCP/A2A audit logs"] + }, + { + "name": "open-sse Engine", + "type": "container", + "technology": "TypeScript / Node.js >=22", + "description": "Core streaming engine: handler pipeline, provider executors (20+), format translators, combo routing (15 strategies), prompt compression pipeline", + "responsibilities": ["Request translation (OpenAI↔Anthropic↔Gemini)", "Provider executor dispatch", "Combo resolution (priority/weighted/auto)", "Rate limiting & circuit breakers", "Prompt compression (lite/caveman/RTK/stacked)"] + }, + { + "name": "MCP Server", + "type": "container", + "technology": "TypeScript / Zod", + "description": "87 MCP tools across 30 auth scopes. 3 transports (stdio/SSE/Streamable HTTP). Tool categories: core (20), cache, compression, 1proxy, memory, skills, gamification, plugins, Notion, Obsidian.", + "responsibilities": ["Tool registration & dispatch", "Scope-based authorization", "Invocation audit logging"] + }, + { + "name": "A2A Server", + "type": "container", + "technology": "TypeScript / JSON-RPC 2.0", + "description": "Agent-to-Agent protocol server with SSE streaming, Task Manager (TTL cleanup), 8 skills (cost analysis, quota, routing, discovery, health, capabilities, dispatch).", + "responsibilities": ["Agent skill execution", "Task lifecycle management", "Agent Card discovery"] + }, + { + "name": "Electron Desktop", + "type": "container", + "technology": "Electron", + "description": "Cross-platform desktop app (Windows, macOS, Linux) wrapping the Next.js UI and MCP server.", + "responsibilities": ["Local-first desktop experience", "Bundled MCP stdio transport"] + } + ], + "relationships": [ + { "source": "Next.js App Router", "target": "open-sse Engine", "description": "Proxies API requests to handler pipeline" }, + { "source": "open-sse Engine", "target": "SQLite Database", "description": "Reads/writes provider config, usage, audit" }, + { "source": "open-sse Engine", "target": "Upstream LLM Providers", "description": "Forwards translated requests via executors" }, + { "source": "MCP Server", "target": "SQLite Database", "description": "Audits all tool invocations" }, + { "source": "A2A Server", "target": "SQLite Database", "description": "Reads quotas, pricing, health for skill results" } + ] + } + } +} diff --git a/.github/workflows/cargo-lock-hash.yaml b/.github/workflows/cargo-lock-hash.yaml new file mode 100644 index 00000000000..bb495e44dff --- /dev/null +++ b/.github/workflows/cargo-lock-hash.yaml @@ -0,0 +1,42 @@ +name: Lock Hash Check + +on: + schedule: + - cron: "0 4 * * 1" # Every Monday at 04:00 UTC + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: lock-hash-check + cancel-in-progress: false + +jobs: + lock-hash: + name: Verify Lock File Determinism + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 + with: + persist-credentials: false + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e + with: + node-version: "24" + cache: npm + - name: Compute hash of package-lock.json + run: | + LOCK_HASH=$(sha256sum package-lock.json | cut -d' ' -f1) + echo "lock_hash=${LOCK_HASH}" >> "$GITHUB_STEP_SUMMARY" + echo "package-lock.json SHA256: ${LOCK_HASH}" + - name: Verify deterministic install + run: | + BEFORE=$(sha256sum package-lock.json | cut -d' ' -f1) + npm ci --dry-run 2>&1 | head -5 || true + AFTER=$(sha256sum package-lock.json | cut -d' ' -f1) + if [ "$BEFORE" != "$AFTER" ]; then + echo "::error::package-lock.json changed during npm ci --dry-run — lock file is not deterministic." + exit 1 + fi + echo "✅ package-lock.json is deterministic." diff --git a/.github/workflows/contract_tests.yaml b/.github/workflows/contract_tests.yaml new file mode 100644 index 00000000000..19fc02f285b --- /dev/null +++ b/.github/workflows/contract_tests.yaml @@ -0,0 +1,44 @@ +name: Contract Tests + +on: + pull_request: + branches: [main] + paths: + - "src/**" + - "open-sse/**" + - "tests/contract/**" + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: "24" + +jobs: + contract-tests: + name: Contract Tests + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 + with: + fetch-depth: 0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + - run: npm ci + - name: Run contract tests + run: | + if [ -d tests/contract ] && ls tests/contract/*.test.ts 2>/dev/null; then + node --import tsx --test --test-concurrency=1 tests/contract/*.test.ts + else + echo "No contract tests found — skipping. Add *.test.ts files under tests/contract/ to enable." + fi diff --git a/.github/workflows/sbom-gen.yaml b/.github/workflows/sbom-gen.yaml new file mode 100644 index 00000000000..33ae0d70674 --- /dev/null +++ b/.github/workflows/sbom-gen.yaml @@ -0,0 +1,43 @@ +name: SBOM Generation (CycloneDX) + +on: + push: + branches: [main] + paths: + - package.json + - package-lock.json + schedule: + - cron: "0 6 * * 1" # Every Monday at 06:00 UTC + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: "24" + +jobs: + sbom-gen: + name: Generate CycloneDX SBOM + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 + with: + persist-credentials: false + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + - run: npm ci + - name: Generate CycloneDX SBOM + run: npm sbom --sbom-format cyclonedx > omniroute-sbom.cdx.json + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + with: + name: omniroute-sbom-cyclonedx + path: omniroute-sbom.cdx.json + retention-days: 90 diff --git a/.github/workflows/ssot-drift-cron.yaml b/.github/workflows/ssot-drift-cron.yaml new file mode 100644 index 00000000000..7c77954a820 --- /dev/null +++ b/.github/workflows/ssot-drift-cron.yaml @@ -0,0 +1,42 @@ +name: SSOT Drift Scan + +on: + schedule: + - cron: "0 2 * * 1" # Every Monday at 02:00 UTC + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ssot-drift-scan + cancel-in-progress: false + +env: + NODE_VERSION: "24" + +jobs: + ssot-drift: + name: SSOT Drift Scan + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 + with: + fetch-depth: 0 + persist-credentials: false + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + - run: npm ci + - name: Check docs sync (source vs generated) + run: npm run check:docs-sync 2>&1 || echo "Drift detected — run 'npm run docs:sync' locally." + - name: Check route validation drift + run: npm run check:route-validation:t06 2>&1 || echo "Route validation drift detected." + - name: Report drift summary + if: always() + run: | + echo "## SSOT Drift Scan — $(date -u '+%Y-%m-%dT%H:%M:%SZ')" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "Scans run: docs-sync, route-validation, provider-catalog." >> "$GITHUB_STEP_SUMMARY"