test: route-level integration tests + app/index split
Ports the backend route-level integration suites from the amal66 fork
(index: Open-Legal-Products/mike#205), adapted from the fork's
apps/api modules/services layout to this repo's monolithic
backend/src/routes/*.ts layout.
app/index split (the only production change; mechanical, zero behavior
change): backend/src/index.ts previously built the express app and
called app.listen at the bottom. Everything except the listen call
moved verbatim into backend/src/app.ts, which now exports `app` (same
middleware order, same routes, same rate-limiter setup, dotenv/config
still imported first). index.ts is now a tiny entry that imports
{ app } and calls listen with the same log line. `npm run build` still
emits dist/index.js and the `start` script is unchanged.
New suites under backend/src/__tests__/integration/ (94 tests):
- health.test.ts (5): /health, requireAuth 401 paths, 404 fallthrough
- chat.routes.test.ts (6): POST /chat validation + SSE happy/error paths
- projects.routes.test.ts (18): overview/create/detail/patch/delete,
sharing normalisation, ownership guards
- projectChat.routes.test.ts (3): project access guard + SSE paths
- tabular.routes.test.ts (31): review CRUD, access guards,
document-access filtering, missing_api_key guards
- user.routes.test.ts (27): profile, API-key crypto boundary, MFA
guards, export/deletion endpoints
- documentsUpload.routes.test.ts (4): upload validation + download-zip
bounds/access
- access.supabase.test.ts (1) + stack.supabase.test.ts (4): gated on
SUPABASE_TEST_URL / SUPABASE_TEST_SERVICE_ROLE_KEY (stack suite also
needs SUPABASE_TEST_ANON_KEY); describe.skip otherwise
- scripts/test-stack.sh + `npm run test:stack`: reads a running
`supabase status -o json` and runs the gated suites
Adds supertest + @types/supertest as devDependencies.
Dropped relative to the fork (subjects that do not exist in this repo):
- orgs.routes, credits.concurrency.supabase, dmsConnectors suites
(fork-only features)
- all credit-reservation cases (429 CREDIT_LIMIT_EXCEEDED,
reserve-then-refund) in chat/projectChat: no credit system here
- health /ready case: no /ready endpoint here
- org-membership project access case: no org model here
- upload magic-byte validation cases: this repo validates extension
only (the fork adds content sniffing; replaced with a missing-file
400 case)
- download-zip 50-document cap case: no cap here (replaced with a
no-accessible-documents 404 case)
- stack.supabase PUBLIC_TABLES updated to this repo's schema; the
fork's credit-RPC coverage is n/a
Verified locally: backend `npm test` -> 8 files passed, 2 skipped;
106 tests passed, 5 skipped (gated suites skip without env).
`npm run build` passes. The gated suites were additionally run against
a live local Supabase stack: 2 files, 5/5 tests passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 11:00:01 -07:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# Run the gated stack-level integration tests against a local Supabase stack.
|
|
|
|
|
#
|
|
|
|
|
# These tests exercise the REAL stack (GoTrue auth + Postgres RLS) instead of
|
|
|
|
|
# mocks. They are the harness you re-run on every Supabase image bump to prove
|
|
|
|
|
# the auth↔API contract and the deny-all RLS firewall still hold.
|
|
|
|
|
#
|
|
|
|
|
# Usage: supabase start # in the repo, once
|
|
|
|
|
# npm run test:stack (from backend/)
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
2026-07-23 19:08:08 +08:00
|
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
|
BACKEND_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
|
SCHEMA_FILE="$BACKEND_DIR/schema.sql"
|
|
|
|
|
|
test: route-level integration tests + app/index split
Ports the backend route-level integration suites from the amal66 fork
(index: Open-Legal-Products/mike#205), adapted from the fork's
apps/api modules/services layout to this repo's monolithic
backend/src/routes/*.ts layout.
app/index split (the only production change; mechanical, zero behavior
change): backend/src/index.ts previously built the express app and
called app.listen at the bottom. Everything except the listen call
moved verbatim into backend/src/app.ts, which now exports `app` (same
middleware order, same routes, same rate-limiter setup, dotenv/config
still imported first). index.ts is now a tiny entry that imports
{ app } and calls listen with the same log line. `npm run build` still
emits dist/index.js and the `start` script is unchanged.
New suites under backend/src/__tests__/integration/ (94 tests):
- health.test.ts (5): /health, requireAuth 401 paths, 404 fallthrough
- chat.routes.test.ts (6): POST /chat validation + SSE happy/error paths
- projects.routes.test.ts (18): overview/create/detail/patch/delete,
sharing normalisation, ownership guards
- projectChat.routes.test.ts (3): project access guard + SSE paths
- tabular.routes.test.ts (31): review CRUD, access guards,
document-access filtering, missing_api_key guards
- user.routes.test.ts (27): profile, API-key crypto boundary, MFA
guards, export/deletion endpoints
- documentsUpload.routes.test.ts (4): upload validation + download-zip
bounds/access
- access.supabase.test.ts (1) + stack.supabase.test.ts (4): gated on
SUPABASE_TEST_URL / SUPABASE_TEST_SERVICE_ROLE_KEY (stack suite also
needs SUPABASE_TEST_ANON_KEY); describe.skip otherwise
- scripts/test-stack.sh + `npm run test:stack`: reads a running
`supabase status -o json` and runs the gated suites
Adds supertest + @types/supertest as devDependencies.
Dropped relative to the fork (subjects that do not exist in this repo):
- orgs.routes, credits.concurrency.supabase, dmsConnectors suites
(fork-only features)
- all credit-reservation cases (429 CREDIT_LIMIT_EXCEEDED,
reserve-then-refund) in chat/projectChat: no credit system here
- health /ready case: no /ready endpoint here
- org-membership project access case: no org model here
- upload magic-byte validation cases: this repo validates extension
only (the fork adds content sniffing; replaced with a missing-file
400 case)
- download-zip 50-document cap case: no cap here (replaced with a
no-accessible-documents 404 case)
- stack.supabase PUBLIC_TABLES updated to this repo's schema; the
fork's credit-RPC coverage is n/a
Verified locally: backend `npm test` -> 8 files passed, 2 skipped;
106 tests passed, 5 skipped (gated suites skip without env).
`npm run build` passes. The gated suites were additionally run against
a live local Supabase stack: 2 files, 5/5 tests passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 11:00:01 -07:00
|
|
|
if ! command -v supabase >/dev/null 2>&1; then
|
|
|
|
|
echo "supabase CLI not found. Install: brew install supabase/tap/supabase" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
STATUS="$(supabase status -o json 2>/dev/null)" || {
|
|
|
|
|
echo "No running Supabase stack. Start one with: supabase start" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
read_key() { node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>process.stdout.write(String(JSON.parse(s)['$1']??'')))" <<<"$STATUS"; }
|
|
|
|
|
|
|
|
|
|
SUPABASE_TEST_URL="$(read_key API_URL)"
|
|
|
|
|
SUPABASE_TEST_SERVICE_ROLE_KEY="$(read_key SERVICE_ROLE_KEY)"
|
|
|
|
|
SUPABASE_TEST_ANON_KEY="$(read_key ANON_KEY)"
|
2026-07-23 19:08:08 +08:00
|
|
|
SUPABASE_TEST_DB_URL="$(read_key DB_URL)"
|
test: route-level integration tests + app/index split
Ports the backend route-level integration suites from the amal66 fork
(index: Open-Legal-Products/mike#205), adapted from the fork's
apps/api modules/services layout to this repo's monolithic
backend/src/routes/*.ts layout.
app/index split (the only production change; mechanical, zero behavior
change): backend/src/index.ts previously built the express app and
called app.listen at the bottom. Everything except the listen call
moved verbatim into backend/src/app.ts, which now exports `app` (same
middleware order, same routes, same rate-limiter setup, dotenv/config
still imported first). index.ts is now a tiny entry that imports
{ app } and calls listen with the same log line. `npm run build` still
emits dist/index.js and the `start` script is unchanged.
New suites under backend/src/__tests__/integration/ (94 tests):
- health.test.ts (5): /health, requireAuth 401 paths, 404 fallthrough
- chat.routes.test.ts (6): POST /chat validation + SSE happy/error paths
- projects.routes.test.ts (18): overview/create/detail/patch/delete,
sharing normalisation, ownership guards
- projectChat.routes.test.ts (3): project access guard + SSE paths
- tabular.routes.test.ts (31): review CRUD, access guards,
document-access filtering, missing_api_key guards
- user.routes.test.ts (27): profile, API-key crypto boundary, MFA
guards, export/deletion endpoints
- documentsUpload.routes.test.ts (4): upload validation + download-zip
bounds/access
- access.supabase.test.ts (1) + stack.supabase.test.ts (4): gated on
SUPABASE_TEST_URL / SUPABASE_TEST_SERVICE_ROLE_KEY (stack suite also
needs SUPABASE_TEST_ANON_KEY); describe.skip otherwise
- scripts/test-stack.sh + `npm run test:stack`: reads a running
`supabase status -o json` and runs the gated suites
Adds supertest + @types/supertest as devDependencies.
Dropped relative to the fork (subjects that do not exist in this repo):
- orgs.routes, credits.concurrency.supabase, dmsConnectors suites
(fork-only features)
- all credit-reservation cases (429 CREDIT_LIMIT_EXCEEDED,
reserve-then-refund) in chat/projectChat: no credit system here
- health /ready case: no /ready endpoint here
- org-membership project access case: no org model here
- upload magic-byte validation cases: this repo validates extension
only (the fork adds content sniffing; replaced with a missing-file
400 case)
- download-zip 50-document cap case: no cap here (replaced with a
no-accessible-documents 404 case)
- stack.supabase PUBLIC_TABLES updated to this repo's schema; the
fork's credit-RPC coverage is n/a
Verified locally: backend `npm test` -> 8 files passed, 2 skipped;
106 tests passed, 5 skipped (gated suites skip without env).
`npm run build` passes. The gated suites were additionally run against
a live local Supabase stack: 2 files, 5/5 tests passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 11:00:01 -07:00
|
|
|
|
2026-07-23 19:08:08 +08:00
|
|
|
if [[ -z "$SUPABASE_TEST_URL" || -z "$SUPABASE_TEST_SERVICE_ROLE_KEY" || -z "$SUPABASE_TEST_ANON_KEY" || -z "$SUPABASE_TEST_DB_URL" ]]; then
|
|
|
|
|
echo "Could not read API_URL/DB_URL/SERVICE_ROLE_KEY/ANON_KEY from 'supabase status'." >&2
|
test: route-level integration tests + app/index split
Ports the backend route-level integration suites from the amal66 fork
(index: Open-Legal-Products/mike#205), adapted from the fork's
apps/api modules/services layout to this repo's monolithic
backend/src/routes/*.ts layout.
app/index split (the only production change; mechanical, zero behavior
change): backend/src/index.ts previously built the express app and
called app.listen at the bottom. Everything except the listen call
moved verbatim into backend/src/app.ts, which now exports `app` (same
middleware order, same routes, same rate-limiter setup, dotenv/config
still imported first). index.ts is now a tiny entry that imports
{ app } and calls listen with the same log line. `npm run build` still
emits dist/index.js and the `start` script is unchanged.
New suites under backend/src/__tests__/integration/ (94 tests):
- health.test.ts (5): /health, requireAuth 401 paths, 404 fallthrough
- chat.routes.test.ts (6): POST /chat validation + SSE happy/error paths
- projects.routes.test.ts (18): overview/create/detail/patch/delete,
sharing normalisation, ownership guards
- projectChat.routes.test.ts (3): project access guard + SSE paths
- tabular.routes.test.ts (31): review CRUD, access guards,
document-access filtering, missing_api_key guards
- user.routes.test.ts (27): profile, API-key crypto boundary, MFA
guards, export/deletion endpoints
- documentsUpload.routes.test.ts (4): upload validation + download-zip
bounds/access
- access.supabase.test.ts (1) + stack.supabase.test.ts (4): gated on
SUPABASE_TEST_URL / SUPABASE_TEST_SERVICE_ROLE_KEY (stack suite also
needs SUPABASE_TEST_ANON_KEY); describe.skip otherwise
- scripts/test-stack.sh + `npm run test:stack`: reads a running
`supabase status -o json` and runs the gated suites
Adds supertest + @types/supertest as devDependencies.
Dropped relative to the fork (subjects that do not exist in this repo):
- orgs.routes, credits.concurrency.supabase, dmsConnectors suites
(fork-only features)
- all credit-reservation cases (429 CREDIT_LIMIT_EXCEEDED,
reserve-then-refund) in chat/projectChat: no credit system here
- health /ready case: no /ready endpoint here
- org-membership project access case: no org model here
- upload magic-byte validation cases: this repo validates extension
only (the fork adds content sniffing; replaced with a missing-file
400 case)
- download-zip 50-document cap case: no cap here (replaced with a
no-accessible-documents 404 case)
- stack.supabase PUBLIC_TABLES updated to this repo's schema; the
fork's credit-RPC coverage is n/a
Verified locally: backend `npm test` -> 8 files passed, 2 skipped;
106 tests passed, 5 skipped (gated suites skip without env).
`npm run build` passes. The gated suites were additionally run against
a live local Supabase stack: 2 files, 5/5 tests passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 11:00:01 -07:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
export SUPABASE_TEST_URL SUPABASE_TEST_SERVICE_ROLE_KEY SUPABASE_TEST_ANON_KEY
|
|
|
|
|
|
2026-07-23 19:08:08 +08:00
|
|
|
if ! command -v psql >/dev/null 2>&1; then
|
|
|
|
|
echo "psql not found. Install PostgreSQL's client tools before running stack tests." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# A newly started local stack contains Supabase's system schemas but none of
|
|
|
|
|
# Mike's application tables. Initialize only an empty stack: silently resetting
|
|
|
|
|
# or modifying an existing application database would be surprising.
|
|
|
|
|
PROJECTS_TABLE="$(
|
|
|
|
|
psql "$SUPABASE_TEST_DB_URL" -XAtq \
|
|
|
|
|
-c "select to_regclass('public.projects');"
|
|
|
|
|
)"
|
|
|
|
|
if [[ "$PROJECTS_TABLE" != "projects" ]]; then
|
|
|
|
|
echo "Mike schema not found; loading $SCHEMA_FILE"
|
|
|
|
|
psql "$SUPABASE_TEST_DB_URL" -X \
|
|
|
|
|
--set ON_ERROR_STOP=1 \
|
|
|
|
|
--file "$SCHEMA_FILE"
|
|
|
|
|
fi
|
|
|
|
|
|
test: route-level integration tests + app/index split
Ports the backend route-level integration suites from the amal66 fork
(index: Open-Legal-Products/mike#205), adapted from the fork's
apps/api modules/services layout to this repo's monolithic
backend/src/routes/*.ts layout.
app/index split (the only production change; mechanical, zero behavior
change): backend/src/index.ts previously built the express app and
called app.listen at the bottom. Everything except the listen call
moved verbatim into backend/src/app.ts, which now exports `app` (same
middleware order, same routes, same rate-limiter setup, dotenv/config
still imported first). index.ts is now a tiny entry that imports
{ app } and calls listen with the same log line. `npm run build` still
emits dist/index.js and the `start` script is unchanged.
New suites under backend/src/__tests__/integration/ (94 tests):
- health.test.ts (5): /health, requireAuth 401 paths, 404 fallthrough
- chat.routes.test.ts (6): POST /chat validation + SSE happy/error paths
- projects.routes.test.ts (18): overview/create/detail/patch/delete,
sharing normalisation, ownership guards
- projectChat.routes.test.ts (3): project access guard + SSE paths
- tabular.routes.test.ts (31): review CRUD, access guards,
document-access filtering, missing_api_key guards
- user.routes.test.ts (27): profile, API-key crypto boundary, MFA
guards, export/deletion endpoints
- documentsUpload.routes.test.ts (4): upload validation + download-zip
bounds/access
- access.supabase.test.ts (1) + stack.supabase.test.ts (4): gated on
SUPABASE_TEST_URL / SUPABASE_TEST_SERVICE_ROLE_KEY (stack suite also
needs SUPABASE_TEST_ANON_KEY); describe.skip otherwise
- scripts/test-stack.sh + `npm run test:stack`: reads a running
`supabase status -o json` and runs the gated suites
Adds supertest + @types/supertest as devDependencies.
Dropped relative to the fork (subjects that do not exist in this repo):
- orgs.routes, credits.concurrency.supabase, dmsConnectors suites
(fork-only features)
- all credit-reservation cases (429 CREDIT_LIMIT_EXCEEDED,
reserve-then-refund) in chat/projectChat: no credit system here
- health /ready case: no /ready endpoint here
- org-membership project access case: no org model here
- upload magic-byte validation cases: this repo validates extension
only (the fork adds content sniffing; replaced with a missing-file
400 case)
- download-zip 50-document cap case: no cap here (replaced with a
no-accessible-documents 404 case)
- stack.supabase PUBLIC_TABLES updated to this repo's schema; the
fork's credit-RPC coverage is n/a
Verified locally: backend `npm test` -> 8 files passed, 2 skipped;
106 tests passed, 5 skipped (gated suites skip without env).
`npm run build` passes. The gated suites were additionally run against
a live local Supabase stack: 2 files, 5/5 tests passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 11:00:01 -07:00
|
|
|
echo "Running stack integration tests against $SUPABASE_TEST_URL"
|
2026-07-23 19:08:08 +08:00
|
|
|
cd "$BACKEND_DIR"
|
test: route-level integration tests + app/index split
Ports the backend route-level integration suites from the amal66 fork
(index: Open-Legal-Products/mike#205), adapted from the fork's
apps/api modules/services layout to this repo's monolithic
backend/src/routes/*.ts layout.
app/index split (the only production change; mechanical, zero behavior
change): backend/src/index.ts previously built the express app and
called app.listen at the bottom. Everything except the listen call
moved verbatim into backend/src/app.ts, which now exports `app` (same
middleware order, same routes, same rate-limiter setup, dotenv/config
still imported first). index.ts is now a tiny entry that imports
{ app } and calls listen with the same log line. `npm run build` still
emits dist/index.js and the `start` script is unchanged.
New suites under backend/src/__tests__/integration/ (94 tests):
- health.test.ts (5): /health, requireAuth 401 paths, 404 fallthrough
- chat.routes.test.ts (6): POST /chat validation + SSE happy/error paths
- projects.routes.test.ts (18): overview/create/detail/patch/delete,
sharing normalisation, ownership guards
- projectChat.routes.test.ts (3): project access guard + SSE paths
- tabular.routes.test.ts (31): review CRUD, access guards,
document-access filtering, missing_api_key guards
- user.routes.test.ts (27): profile, API-key crypto boundary, MFA
guards, export/deletion endpoints
- documentsUpload.routes.test.ts (4): upload validation + download-zip
bounds/access
- access.supabase.test.ts (1) + stack.supabase.test.ts (4): gated on
SUPABASE_TEST_URL / SUPABASE_TEST_SERVICE_ROLE_KEY (stack suite also
needs SUPABASE_TEST_ANON_KEY); describe.skip otherwise
- scripts/test-stack.sh + `npm run test:stack`: reads a running
`supabase status -o json` and runs the gated suites
Adds supertest + @types/supertest as devDependencies.
Dropped relative to the fork (subjects that do not exist in this repo):
- orgs.routes, credits.concurrency.supabase, dmsConnectors suites
(fork-only features)
- all credit-reservation cases (429 CREDIT_LIMIT_EXCEEDED,
reserve-then-refund) in chat/projectChat: no credit system here
- health /ready case: no /ready endpoint here
- org-membership project access case: no org model here
- upload magic-byte validation cases: this repo validates extension
only (the fork adds content sniffing; replaced with a missing-file
400 case)
- download-zip 50-document cap case: no cap here (replaced with a
no-accessible-documents 404 case)
- stack.supabase PUBLIC_TABLES updated to this repo's schema; the
fork's credit-RPC coverage is n/a
Verified locally: backend `npm test` -> 8 files passed, 2 skipped;
106 tests passed, 5 skipped (gated suites skip without env).
`npm run build` passes. The gated suites were additionally run against
a live local Supabase stack: 2 files, 5/5 tests passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 11:00:01 -07:00
|
|
|
exec npx vitest run \
|
|
|
|
|
src/__tests__/integration/stack.supabase.test.ts \
|
|
|
|
|
src/__tests__/integration/access.supabase.test.ts \
|
|
|
|
|
"$@"
|