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
88 changes: 88 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: CI

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
quality:
name: Node 20 quality and security
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- name: Check out source
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 20.19.5
cache: npm

- name: Install locked dependencies
run: npm ci

- name: Type-check
run: npm run type-check

- name: Lint
run: npm run lint

- name: Unit tests and coverage
run: npm test -- --runInBand --coverage

- name: Build
run: npm run build

- name: Production dependency audit
run: npm audit --omit=dev --audit-level=high

postgres-integration:
name: PostgreSQL integration
runs-on: ubuntu-24.04
timeout-minutes: 15
services:
postgres:
image: pgvector/pgvector@sha256:7b822b0aac60967beb1ea5e576b8602c94c300a157d187f385ae3e0da199b90a
env:
POSTGRES_DB: ruvector-postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: adr1test
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d ruvector-postgres"
--health-interval 5s
--health-timeout 5s
--health-retries 12
env:
RUVVECTOR_DB_HOST: localhost
RUVVECTOR_DB_PORT: 5432
RUVVECTOR_DB_NAME: ruvector-postgres
RUVVECTOR_DB_USER: postgres
RUVVECTOR_DB_PASSWORD: adr1test
RUVVECTOR_EMBEDDING_DIM: 4
EXECUTION_HMAC_SECRET: test-hmac-secret-minimum-32-chars-long
steps:
- name: Check out source
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 20.19.5
cache: npm

- name: Install locked dependencies
run: npm ci

- name: Run real PostgreSQL integration tests
run: npm run test:integration -- --runInBand
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Dependencies
node_modules/
package-lock.json

# Build output
dist/
Expand Down Expand Up @@ -47,4 +46,7 @@ pids/
.claude/
.claude-flow/
.mcp.json
CLAUDE.md

# Local MetaHarness evaluation artifacts
.metaharness/
CLAUDE.md
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

<p align="center">
<img src="https://img.shields.io/badge/license-ISC-blue?style=flat-square" alt="License" />
<img src="https://img.shields.io/badge/coverage-99%25-brightgreen?style=flat-square" alt="Coverage" />
<img src="https://img.shields.io/badge/coverage-70%25_minimum-brightgreen?style=flat-square" alt="Coverage gate: 70% minimum" />
<img src="https://img.shields.io/badge/status-production-success?style=flat-square" alt="Status" />
</p>

Expand Down
45 changes: 45 additions & 0 deletions docs/adr/ADR-0004-persist-service-artifacts-in-postgresql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# ADR-0004: Persist service artifacts in PostgreSQL

## Status

Accepted

## Context

The lineage, ERP mapping, and integration proposal endpoints stored records in
process-local `Map` instances. Cloud Run can start multiple instances and can
replace any instance at any time. A process-local store therefore loses records
on restart and produces different answers depending on which instance handles a
request.

`ruvector-service` already owns the configured RuVector PostgreSQL connection.
The service must remain stateless and must not introduce another database.

## Decision

Store lineage records, ERP mappings, and integration proposals in append-only
tables in the existing PostgreSQL database. Create the tables idempotently
during database initialization. Bind every request value as a query parameter,
return `409 immutable_conflict` when a caller reuses an identifier, and do not
provide mutation or deletion endpoints for these evidence records.

Exercise the handlers with unit tests and exercise persistence across two
Express application instances with PostgreSQL 16 plus pgvector in Linux CI.
Pin the CI actions and service image by immutable revision or digest, and use a
committed npm lock file for deterministic dependency installation.

## Consequences

- Records survive process replacement and remain consistent across instances.
- The existing RuVector-backed PostgreSQL service remains the only persistence
layer.
- Deployments require the configured database to be reachable; failures remain
fail-closed instead of silently falling back to process memory.
- Schema initialization remains intentionally additive. A future managed
migration workflow can adopt the tables without changing their contracts.

## Rollback

Revert the implementation commit to restore the previous handlers and schema
initialization. This leaves the additive tables and their audit records intact;
dropping them is a separate, explicitly reviewed database operation.
Loading
Loading