Skip to content

Reference index: the amal66 fork, decomposed into 25 reviewable PRs - #205

Closed
amal66 wants to merge 197 commits into
Open-Legal-Products:mainfrom
amal66:feat/tier1-deal-closers
Closed

Reference index: the amal66 fork, decomposed into 25 reviewable PRs#205
amal66 wants to merge 197 commits into
Open-Legal-Products:mainfrom
amal66:feat/tier1-deal-closers

Conversation

@amal66

@amal66 amal66 commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

This PR is a reference index — it is not meant to be merged. It maps everything in the amal66 fork onto small, individually reviewable PRs, so you can point at any row and take exactly that piece (or port it yourself — CLA signed, credit is enough).

What this is

The amal66 fork has tracked this repo since May (currently 0 commits behind; your UI kept verbatim as the source of truth — my changes are re-ported onto yours after every sync, never the reverse). This index decomposes the fork's entire delta into 25 standalone PRs, each:

  • based on a mirror of this repo's main (branch upstream-main on amal66/mike), in this repo's own layout (backend/ + frontend/) — so every diff reads exactly as it would arrive here;
  • one concern per PR, in the CONTRIBUTING format (summary / changes / why / testing);
  • carrying its tests, and a Provenance section proving each hunk is a mechanical port of code running in the fork — no logic invented during extraction;
  • one push away from becoming a PR on this repo, whenever wanted (see Recommended merge order below for the only sequencing that matters).

Recommended merge order

Every row below is an independent diff against upstream-main and applies cleanly on its own, so any single row can still be taken in isolation. If you take several, the order only matters in the three places below — this is the sequence that keeps them conflict-free:

  1. Safety net firstamal66#24 (vitest harness). Every other row's tests ride on it.
  2. Small security & self-contained rows — any order among themselvesamal66#26 SSRF, amal66#25 citation verification, amal66#30 download-token expiry, amal66#32 connector-secret encryption, amal66#31 CORS, amal66#29 spotlighting. Each edits routes/libs in place; no cross-conflicts.
  3. Extensibility base, then its stackamal66#27 provider registry before amal66#28 demo mode, amal66#34 Ollama, amal66#48 Vertex (they build on Is there a cookbook how to install Mike? #27). Independent siblings amal66#35, amal66#33, amal66#39, amal66#47, amal66#44 fit anywhere in this band.
  4. Architecture (read the ADR first)amal66#38 organizations; amal66#40 durable queues before amal66#41 RAG (RAG builds on the queue).
  5. Clients & proof — anytimeamal66#43 e2e, amal66#45 evals, amal66#46 CI, amal66#37 Word add-in. Fully self-contained; zero route overlap.
  6. The backend reorganization LASTamal66#42 service layers. It is the one row that relocates code: it retires 7 backend/src/routes/*.ts files into 41 backend/src/modules/* files. Taken last, it reconciles against the finished route set in a single pass; taken earlier, every route-touching row above (Features/integration with scout #40, Security hardening: system prompt confidentiality, PII boundaries, and tool use guardrails #38, fix(security): remove persisted Claude raw stream log #29, Add Docker Compose dev stack and local Supabase setup #44, Externalize built-in workflows into declarative workflow packs #33, Local LLM possible? #41) would need re-porting onto the new module layout. If you'd rather not adopt the module layout at all, skip it — nothing else depends on it.

Two hard rules regardless of the above: #27 → #28 / #34 / #48 and #40 → #41 — a stacked row needs its base merged first. The only routine friction is lockfile churn: rows that add a dependency touch backend/package.json / package-lock.json; regenerate the lockfile on merge and it's gone.

The tables below are the same 25 rows grouped by theme, with sizes and detail.

Start here (small, self-contained, zero new hosting cost)

PR What it does Size
amal66#24 Minimal vitest harness (this repo has no test runner; dev-deps only) — the safety net every other row's tests ride on S
amal66#26 SSRF guardrails: connector URLs can't make the server fetch internal/cloud-metadata addresses (incl. DNS-rebinding pinning) S
amal66#25 Citation verification: every quoted citation is checked against the actual document text server-side — pure string matching, no extra LLM calls S
amal66#28 Demo mode: first-run users (and journalist demos) get a real answer with zero API keys instead of an error (stacks on #27) M
amal66#29 Prompt-injection spotlighting: untrusted document text is nonce-fenced so it can't impersonate instructions S

Security pack (one topic per PR)

PR What it does Size
amal66#32 MCP connector secrets encrypted with per-record derived keys (no migration needed; legacy rows still decrypt) S
amal66#30 Download tokens without an expiry are rejected instead of living forever S
amal66#31 Production CORS allowlist + external tools default to requiring confirmation S

Reliability & interchange

PR What it does Size
amal66#33 Tabular review streams auto-resume after network drops — cells keep filling instead of silently freezing (server heartbeats deferred to #170, which covers them) M
amal66#35 .mikeworkflow.json export/import with optional language/jurisdictions metadata — a UK pack isn't a US pack (feeds the SKILL.md workflows direction) M

Extensibility & local inference ("files never leave the building")

PR What it does Size
amal66#27 Provider registry: adding an LLM provider stops requiring edits at every call site M
amal66#34 Local LLMs via Ollama (OpenAI-compatible endpoints — the approach endorsed in #20), off unless ENABLE_OLLAMA is set (stacks on #27) M
amal66#39 Optional OpenTelemetry + Sentry — provably inert unless configured; AIRGAPPED=true is a hard kill switch M
amal66#44 DMS connectors: iManage and NetDocuments behind a pluggable interface — Mike reads documents where the firm already keeps them M
amal66#47 Pluggable storage adapter: R2 behavior preserved verbatim, GCS added, S3 region configurable M
amal66#48 Vertex AI provider (stacks on #27) S

Architecture (each opens with a design doc — read the ADR before the diff)

PR What it does Size
amal66#38 Multi-tenant organizations with owner/admin/member roles — a firm is not one user L
amal66#40 Durable job queues (BullMQ) for conversion/extraction — all flags default off; no Redis required for a small self-host L
amal66#41 RAG: pgvector retrieval + a search_documents tool, inside the firm's own database (stacks on #40) L
amal66#42 Service layers: route monoliths decomposed into tested modules — endpoint parity verified, 93 tests carried. Relocates route files — merge last (see Recommended merge order). XL
amal66#36 Self-host & air-gap stack: one-step Docker, embedded Supabase, AIRGAPPED mode — fully self-contained (no dependency on any other PR), opt-in files that change nothing for non-Docker users. Where it overlaps the community's open Docker PRs (#196/#149), happy to reconcile with their authors rather than compete — but it stands alone either way L

Clients & end-to-end proof

PR What it does Size
amal66#43 Playwright e2e suite (auth, chat, projects, tabular, workflows) — 27 tests, verified green against a live stack built from this repo's own schema + migrations M
amal66#45 Evals harness — dependency-free prompt-safety/behavior gates (8 checks, failure gate proven) S
amal66#46 CI workflow — build + test jobs that no-op gracefully until the pieces they cover merge, safe in any order S
amal66#37 Word add-in: chat, tracked-changes rewrites, workflows and projects inside Word — 57 hermetic browser scenarios. Lives in the fork's namespace; PR exists so the work is reviewable in this repo's shape XL

Deliberately not offered upstream

Stripe billing (amal66#11) and the programmatic API/SDK surface (amal66#12) stay fork-only unless you ever want them — you've said there are no commercialisation plans, and they'd be new maintenance surfaces.

Ground rules

Small PRs on your terms, in any order including none; anything you'd rather port yourself, take it — credit is enough; everything I land, I maintain (each PR states a triage commitment, and if I go dark for 60 days, revert freely — the rungs are sequenced to be independently revertible); nothing lands while your licence decision is open without us talking first.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CEguyEgXa9JjCciXCcVemC

amal66 added 30 commits May 24, 2026 12:46
Chapter: 01 - Repository shape.

Plain-English map:
Move the project from flat `backend/` and `frontend/` folders into a
workspace layout: `apps/api`, `apps/web`, and shared `packages/*`.
This makes the codebase easier to walk because each folder has a clear job.

Why it matters:
A contributor should not need private context to know where the API, web app,
shared types, client package, or SDK live. The repo structure should teach the
project before anyone opens a README.

Principle:
Make the project legible before making it bigger. Monorepos work best when
each workspace owns one understandable responsibility.

Precedent borrowed:
The fork report showed active forks splitting concerns, adding SDK surfaces,
and creating deployment-specific structure. This commit turns that pressure
into a stable workspace map.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: b587d63.
Chapter: 02 - Open-source collaboration.

Plain-English map:
Add a code of conduct, security policy, issue templates, and a pull request
template. These files tell people how to report bugs, propose changes, and
disclose vulnerabilities without guessing.

Why it matters:
Open-source projects are not only code. They need a shared operating manual
so first-time contributors know the rules of the room and maintainers get the
information they need.

Principle:
Healthy collaboration is documented. A project should make the safe path the
obvious path, especially for security reports.

Precedent borrowed:
GitHub community-health conventions and the security-reporting guidance
requested in upstream PR Open-Legal-Products#147.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 045bdb7.
Chapter: 03 - Database evolution.

Plain-English map:
Introduce Supabase CLI configuration and timestamped migrations so database
changes can be reviewed, applied, and repeated over time.

Why it matters:
A single schema file shows what the database looks like today, but not how it
got there. Migrations tell future maintainers when and why the shape changed.

Principle:
Schema changes should be versioned like application code. Existing deployments
need an incremental path instead of a one-shot reset.

Precedent borrowed:
The fork report's Docker/local-development cluster, Supabase practice, and
upstream PR Open-Legal-Products#113's database-integrity work.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: bc72e34.
Chapter: 04 - Runtime safety basics.

Plain-English map:
Validate required environment variables at startup, reuse Supabase and storage
clients instead of recreating them per request, and remove a timing leak from
download-token comparison.

Why it matters:
Bad configuration should be caught before users hit the app. Shared clients
avoid needless connection churn. Secret checks should not reveal clues through
response timing.

Principle:
Fail fast, reuse expensive resources, and compare secrets in constant time.

Precedent borrowed:
Upstream PRs Open-Legal-Products#81, Open-Legal-Products#106, and Open-Legal-Products#109, which independently targeted timing-safe
comparison, env validation, and singleton client reuse.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: c2d2a9a.
Chapter: 05 - Observability.

Plain-English map:
Add Pino JSON logging and attach a request ID to each request so related log
lines can be traced together in production.

Why it matters:
Plain text logs are hard to search once many users are active. Structured logs
let operators answer practical questions like "what happened during this one
failed upload?"

Principle:
Production logs should be queryable, consistent, and tied to request context.

Precedent borrowed:
Upstream PR Open-Legal-Products#156 and common production logging practice in hosted services.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 6f59af5.
Chapter: 06 - Privacy-aware logging.

Plain-English map:
Replace ad hoc console logging with structured logger calls and remove log
lines that exposed user/document activity identifiers.

Why it matters:
Legal-document activity is sensitive. Logs often flow to third-party systems,
so they should contain only what is useful for debugging and operations.

Principle:
Minimize sensitive data. Treat logs as production data, not scratch paper.

Precedent borrowed:
Upstream PR Open-Legal-Products#80 and GDPR-style data-minimization practice.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 9398be6.
Chapter: 07 - Deployable hardening.

Plain-English map:
Add API and frontend security headers, wire the structured request logger into
the Express app, and add a readiness endpoint that checks whether dependencies
are available.

Why it matters:
Browsers and platforms need clear signals. Security headers reduce browser-side
risk, while readiness checks tell deploy platforms when the app can actually
serve traffic.

Principle:
Defense in depth plus honest health checks.

Precedent borrowed:
Upstream PR Open-Legal-Products#78 and standard container/load-balancer practice that separates
liveness from readiness.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 73ff97a.
Chapter: 08 - Workspace independence.

Plain-English map:
Add the API package metadata, TypeScript config, and Vitest config needed for
`apps/api` to build, run, and test as a clear workspace.

Why it matters:
After the monorepo move, each workspace needs its own local controls. A new
contributor should be able to enter `apps/api` and understand its commands.

Principle:
Every package should be independently understandable even inside a monorepo.

Precedent borrowed:
Monorepo conventions used by larger TypeScript open-source projects and by
forks that split Mike into clearer package boundaries.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 377d685.
Chapter: 09 - Physical source move.

Plain-English map:
Move the API implementation files from the old backend location into
`apps/api` so the directory structure and package boundaries match.

Why it matters:
The repo should not say one thing in package metadata and another thing in its
file layout. Matching structure reduces mental bookkeeping for readers.

Principle:
Make ownership visible in the filesystem.

Precedent borrowed:
The same workspace and modularization pattern introduced in Chapter 01.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: d1ec379.
…ccess guards

Chapter: 10 - API boundaries.

Plain-English map:
Introduce a module layer for API routes, validate incoming request shapes with
Zod, and add authorization checks around tabular document access.

Why it matters:
Large route files make it hard to see where trust boundaries are. Validation
and access checks need to sit at the boundary before data reaches deeper code.

Principle:
Validate inputs and authorize data access close to the edge of the system.

Precedent borrowed:
Upstream PR Open-Legal-Products#155 and the fork report's strongest security signal: multiple
forks independently patched CWE-639 style tabular-document access bugs.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: f913869.
Chapter: 11 - First regression tests.

Plain-English map:
Add Vitest tests for download tokens, storage-path helpers, and user API-key
encryption behavior.

Why it matters:
These helpers sit near sensitive boundaries. If they regress, users can lose
access, leak secrets, or store files in the wrong place.

Principle:
Test the sharp edges first.

Precedent borrowed:
The fork report highlighted several forks with meaningful test suites. This
starts that same protection around core helper behavior.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 4fdc779.
Chapter: 12 - Continuous integration.

Plain-English map:
Add a GitHub Actions pipeline for tests, builds, migration checks, and deploy
gating.

Why it matters:
Reviewers should not have to run every check by hand. CI gives maintainers and
contributors a shared, repeatable answer about whether a change is ready.

Principle:
Make correctness checks part of the merge path.

Precedent borrowed:
Downstream AGPL disclosures and testing-focused forks that added CI around
backend and document-processing behavior.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: e3d2728.
Chapter: 13 - Bounded external calls.

Plain-English map:
Add a three-minute timeout around LLM server-sent-event streams so a stalled
provider call cannot hold a connection open forever.

Why it matters:
External services can hang. Without a timeout, one stuck call can consume
server resources until something outside the app kills it.

Principle:
Every external dependency call should have a clear time boundary.

Precedent borrowed:
Upstream PR Open-Legal-Products#112.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 8992d98.
Chapter: 14 - Secret lifetime.

Plain-English map:
Add a 30-day expiration to signed download tokens while keeping old tokens
backward compatible.

Why it matters:
A signed link should not be useful forever. Shorter lifetimes reduce the
damage if a link is copied, leaked, or found later.

Principle:
Secrets and bearer tokens should expire.

Precedent borrowed:
Upstream PR Open-Legal-Products#77.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: e6bfeb1.
Chapter: 15 - Database defense in depth.

Plain-English map:
Enable Row Level Security fallback policies that deny browser/client roles by
default on public tables.

Why it matters:
The backend uses a service role, but mistakes happen. If a future grant or
client path exposes a table, the database should still default to no access.

Principle:
Least privilege by default, with explicit access instead of accidental access.

Precedent borrowed:
Upstream PR Open-Legal-Products#145.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: faa098c.
Chapter: 16 - Consistent identity matching.

Plain-English map:
Lowercase emails before checking whether a user has shared access to a
project.

Why it matters:
People do not think of email case as meaningful. Access checks that disagree
with that expectation create confusing denials and uneven security behavior.

Principle:
Normalize identity fields before comparing them.

Precedent borrowed:
Upstream PR Open-Legal-Products#79.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: e740508.
Chapter: 17 - Resource limits.

Plain-English map:
Add `limit` and `before` cursor support to chat history loading so the API
does not return an unbounded number of chats in one request.

Why it matters:
Unbounded endpoints are easy to misuse accidentally and easy to stress on
purpose. Pagination keeps response sizes predictable.

Principle:
Public API reads should be bounded and page through large data sets.

Precedent borrowed:
Upstream PR Open-Legal-Products#110.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: b52b04f.
Chapter: 18 - Operational guardrails.

Plain-English map:
Reduce the accepted JSON body size and add handlers that log unhandled
promise rejections and uncaught exceptions.

Why it matters:
Large request bodies can create memory pressure. Unexpected crashes should
leave useful logs so operators can understand what happened.

Principle:
Bound inputs and surface failures clearly.

Precedent borrowed:
The fork report's security-hardening cluster, where many forks added basic
abuse and reliability guardrails.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: d70fde7.
Chapter: 19 - Automated review.

Plain-English map:
Add ESLint for the API workspace, including TypeScript and security-oriented
rules.

Why it matters:
Linters catch repetitive mistakes before a human reviewer spends attention on
them. That frees review time for product and architecture questions.

Principle:
Automate the boring parts of code review.

Precedent borrowed:
Open-source CI hygiene and the fork report's broad hardening pattern.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 276d1fa.
Chapter: 20 - Maintenance flow.

Plain-English map:
Add Dependabot configuration and CODEOWNERS so dependency updates arrive
regularly and sensitive paths route to designated reviewers.

Why it matters:
Open-source maintenance gets easier when updates are routine and review
responsibility is explicit.

Principle:
Make maintenance systematic instead of heroic.

Precedent borrowed:
GitHub dependency-management and ownership conventions used across mature
open-source projects.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 5723a73.
Chapter: 21 - Security checks in the merge path.

Plain-English map:
Add npm audit and ESLint security scanning to the CI pipeline.

Why it matters:
Dependency risk and unsafe patterns should show up during pull request review,
not after deployment.

Principle:
Security automation belongs where code is merged.

Precedent borrowed:
The fork report's dominant security PR cluster and common CI hardening
practice.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 8cda4ca.
Chapter: 22 - User API key protection.

Plain-English map:
Replace static SHA-256 key derivation with HKDF and a unique salt per stored
user API key row.

Why it matters:
Users may store real provider keys in Mike. Those keys deserve standard,
reviewable cryptography instead of one shared derived key for every row.

Principle:
Use established key-derivation functions and per-record salts for encrypted
secrets.

Precedent borrowed:
Upstream PR Open-Legal-Products#76.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: e0a64bd.
Chapter: 23 - Server-side quota enforcement.

Plain-English map:
Check a user's monthly message credits before making chat LLM calls.

Why it matters:
A UI counter alone does not enforce anything. The backend must stop expensive
provider calls when a user has reached the configured limit.

Principle:
Billing and quota rules must be enforced server-side.

Precedent borrowed:
Upstream PR Open-Legal-Products#157.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: fa433e1.
…ense

Chapter: 24 - LLM threat modeling.

Plain-English map:
Fence document text, filenames, and other untrusted content with nonce-marked
spotlighting so the model can better separate data from instructions.

Why it matters:
Legal documents can contain malicious or simply confusing text. The model
should be told which text came from the user, which came from a document, and
which instructions are trusted.

Principle:
An LLM is not a security boundary. Prompts should preserve provenance and make
untrusted content explicit.

Precedent borrowed:
Upstream PR Open-Legal-Products#158 and the threat model documented in `docs/SECURITY-MODEL.md`.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: bededdd.
Chapter: 25 - Upload trust boundary.

Plain-English map:
Check uploaded files by their magic bytes, not only by their filename or
extension.

Why it matters:
A file can be renamed to look harmless. The backend should inspect the actual
file signature before accepting it as a supported document type.

Principle:
Trust content, not labels.

Precedent borrowed:
Upstream PR Open-Legal-Products#78 and standard upload-validation practice.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: c6dd2ec.
Chapter: 26 - Sensitive-path observability.

Plain-English map:
Replace remaining console logging in `chatTools.ts` with the same structured
Pino logger used elsewhere.

Why it matters:
`chatTools.ts` assembles prompts and handles model tool calls. It should have
the same traceability and privacy discipline as the rest of the API.

Principle:
Observability conventions should be consistent, especially in sensitive code.

Precedent borrowed:
Upstream PR Open-Legal-Products#156 and the structured logging baseline from Chapter 05.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 921ef5b.
Chapter: 27 - Self-hosting path.

Plain-English map:
Add Dockerfiles and Docker Compose configuration so contributors can run a
local web/API setup with less manual environment work.

Why it matters:
If local setup is fragile, forks drift because everyone solves deployment
differently. A supported path keeps more work shareable upstream.

Principle:
Self-hosting should be boring and documented.

Precedent borrowed:
Upstream PRs #44, Open-Legal-Products#63, and Open-Legal-Products#149 plus the fork report's large local/self-hosted
stack cluster.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: b2ae01c.
Chapter: 28 - Request-level testing.

Plain-English map:
Extract an app factory from process startup and add Supertest integration
tests that exercise the API through HTTP-style requests.

Why it matters:
Unit tests protect small functions. Integration tests catch mistakes in route
wiring, middleware order, and app startup assumptions.

Principle:
Test important boundaries at the level where users and clients hit them.

Precedent borrowed:
The fork report's testing leaders and downstream backend test coverage.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 9549258.
Chapter: 29 - Provider resilience.

Plain-English map:
Wrap LLM provider calls with exponential-backoff retries for temporary errors
like rate limits, timeouts, and provider outages.

Why it matters:
LLM providers occasionally fail for reasons the user cannot fix. A short,
careful retry can turn a temporary outage into a normal response.

Principle:
Classify external failures before retrying. Retry transient problems, not bad
requests or authentication errors.

Precedent borrowed:
The fork report's alternative-provider cluster and provider-abstraction work
across active forks.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 1417930.
Chapter: 30 - Database identity integrity.

Plain-English map:
Convert nine `user_id` columns from text to UUID and attach them to Supabase
Auth users with foreign keys.

Why it matters:
Supabase user IDs are UUIDs. Storing them as plain text allows invalid values
and orphaned rows that the database cannot protect against.

Principle:
Let the database enforce identity shape and relationships.

Precedent borrowed:
Upstream PR Open-Legal-Products#113.

Upstream base: Open-Legal-Products/mike@d39f580.
Original local commit: 5c28df3.
willchen96 and others added 8 commits July 9, 2026 19:18
Cherry-picked from upstream Open-Legal-Products/mike (82dcaef), adapted to the
monorepo layout (backend/->apps/api, frontend/->apps/web). Upstream's relocated
web primitives (app/components/ui, app/contexts, app/lib) adopted as canon and
local imports rewritten; upstream UI and behavior kept, local infra preserved.

(cherry picked from commit 82dcaef)
- re-point chat/projectChat integration test mocks at the new lib/chat
  surface; seed user_profiles for the new share validation (+1 new test)
- single-instance @tiptap/core via root override + lockfile dedupe
- drop the client-side builtin-workflows shim ([id] redirect now resolves
  system workflows via the API) and the orphaned assistant-message/ dir
- fix packages/shared/ui/pill-button cn import; remove dangling badge shim
  and slug.test.ts (their sources were removed upstream)
Upstream's PR Open-Legal-Products#206 (workflow/UI/Excel+PPT/modal updates) was already ported
into this fork's monorepo layout by commits 5683db0, 82e1eee and 1e21622 --
their content lives under apps/web and apps/api rather than frontend/ and
backend/.

Because those were cherry-picks, git never recorded the ancestry edge: the
merge-base with olp/main stayed at 93f921b, leaving main "3 behind" and every
GitHub merge check red. Replaying the range produced 123 conflicts, 97 of them
purely locational ("added in a directory that was renamed in main").

This commit records the merge without changing a single file. The tree is
byte-identical to 1e21622; olp/main becomes an ancestor; the base advances to
e32daad so future upstream syncs no longer re-fight the restructure.

Parity with upstream was verified before recording:
  - 118/207 upstream-touched files byte-identical to ours
  - 310/310 UI strings and 341/342 symbols upstream added are present
  - the one absent symbol (loadProjects) is upstream's useEffect fetch helper,
    superseded here by useProjectsQuery (React Query)

Policy: upstream wins for features and UI; this fork wins for architecture.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…kflows

The upstream sync (olp/main @ e32daad) reshaped UI the Playwright suite asserts
on. None of it was a regression — the specs were describing the old shape.

  * NewProjectModal and NewTRModal are now two-step wizards ("Details" → "Add
    Documents"). The submit button only exists on the second step, so every
    spec that created a project or review was clicking a button that no longer
    existed there. They now click "Next" first — with exact:true, since
    Next.js's own "Open Next.js Dev Tools" button also matches /Next/.
  * The project row menu offers "Edit details" (ProjectDetailsModal), not an
    inline "Rename"; upstream shipped its own version of that modal.
  * The upload footer button is labelled "Upload (n)", not "Upload files (n)".
  * Upstream renamed builtin-cp-checklist from "Generate CP Checklist" to
    "Draft CP Checklist", and single-sources built-ins in the generated
    lib/systemWorkflows.ts rather than a hand-written builtinWorkflows.ts.
  * NewTRModal's template control is a button reading "No template - start from
    scratch" (hyphen, not em dash).
  * Upstream accepts Excel and PowerPoint, so the rejection copy is now
    "Only PDF, Word, Excel, and PowerPoint files can be uploaded."

createProject and the critical path also got more headroom: the modal mounts
FileDirectory on its second step, whose useDirectoryData fires a getProject()
per existing project, so creation alone could consume a 120s budget and starve
the assertions after it. Both were timeouts, not failures — the demo reply and
the delete action were verified by hand in a browser.

Separately, scripts/build-workflows.js still wrote its output to
backend/src/lib/systemWorkflows.ts, a path this fork's restructure removed.
Unlike the landing-page write it has no existsSync guard, so regenerating the
system workflows would have died with ENOENT. Nothing in package.json or CI
invokes it, so no test could have caught this. Repointed at apps/api.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Taking upstream's message/useSmoothedReveal.ts wholesale during the olp/main
sync reverted a fix this fork already carried. Upstream's `!active` branch
assigns the ref but never the state:

    if (!active) {
        revealedFloat.current = text.length;
        return;                       // <- no setRevealedInt
    }

The rendered slice is driven by `revealedInt`, so when a stream ends before the
rAF pacer has caught up the message freezes on a partial prefix. Reproduced in
a browser: a demo-model reply in a project with no documents rendered as the
literal characters "**Demo mo" and never advanced; reloading the page showed
the full, correctly-formatted answer, confirming the data was fine and only the
live reveal was stuck.

It only bites when the content event is the last renderable one. A reply
followed by document-read or citation events isn't smoothed (see
AssistantMessage's contentIsTail), which is why chat against a project WITH
documents looked fine and this went unnoticed.

Restores both dropped setRevealedInt calls — the snap, and the defensive clamp
for a shortened text (that one is masked by the Math.min on the return, but
leaves state inconsistent). The added test fails against upstream's version
with `expected '' to be '**Demo mode** …'`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…header

Upstream's TablePrimitive renders the header row at z-[70]. The projects
bulk-actions dropdown ("Actions" → "Delete", shown once rows are selected) sits
at z-50 and is drawn underneath it, so the header swallows the click and
selected projects cannot be deleted at all. Verified in a browser at 1280x720:
elementFromPoint over the Delete button returns the sticky header div, and
Playwright reports `<div role="row" class="sticky … z-[70]"> … intercepts
pointer events`.

This fork had no sticky header before the olp/main sync, so the z-50 menu was
fine; the collision arrived with upstream's table primitive. Upstream carries
the same defect (its ProjectsOverview menu is also z-50) but had already solved
it in WorkflowList with z-[100], so this adopts that value. ProjectsOverview is
the only component that both renders the sticky header and owns a z-50
top-full dropdown.

Also fixes the delete-chat spec, which renamed a freshly-created chat to a
unique title without waiting for auto title-generation to land. The rename spec
guards that race; this one did not, so POST /chat/<id>/generate-title could
overwrite the title and the row could no longer be located.

Both were previously masked: delete-a-project burned its whole 180s budget
retrying an unclickable button, which read as a timeout rather than a defect.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…code

`npm run lint` (a required CI check, ci.yml) failed on three spots that arrived
with the olp/main sync. Upstream's backend eslint has no `no-console` rule and
does not run the React Compiler lint, so this code was clean there but not under
apps/api's `no-console: error` and apps/web's react-hooks compiler check.

- chat/contextBuilders.ts: two console.error calls persisting assistant events
  now go through the pino `logger` (logger.error({ err }, "…")), matching every
  other error path in apps/api/src/modules.
- chat/types.ts: `devLog` is an intentional dev-only console.log passthrough
  used ~60x for local tracing; scoped it with eslint-disable-next-line no-console
  rather than routing it through the structured logger.
- modals/PeopleModal.tsx: a manual useMemo tripped the React Compiler's
  "existing memoization could not be preserved" error. Replaced with a plain
  derivation (the compiler memoizes it) and dropped the now-unused import.

All logging/refactor only — no behavior change. Full local gauntlet green:
lint, typecheck, build, unit (api 515, web 73, api-client 10, sdk-js 14),
evals 100%, python-sdk 16, Playwright e2e 27/27.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…en-Legal-Products#216)

Port the upstream Open-Legal-Products/mike UI delta (e32daad..olp/main) into
this fork's monorepo, using olp's UI as the source of truth while preserving
our architecture (packages, @mike/api-client, split components) and functional
features (react-query hooks, readSSE, Demo model fallback, security hardening,
table accessibility roles).

Frontend (apps/web):
- New: DocTable (shared doc table), LibraryWorkspace + /library routes,
  QuickActionsModal, UploadOverlay, liquid-surface/dropdown/tab-pill UI,
  skeuomorphic sidebar + file-type SVG icons.
- Refreshed shared table UI, liquid surfaces, document review panels, sidebar.
- DocumentSidePanel moved projects/ -> shared/; HeaderFilterDropdown removed;
  ProjectDocumentsView slimmed to delegate to DocTable; TRChatPanel UI ported
  into our tr-chat-panel/* split.
- Ported olp UI while keeping our features: emptyStates preview, TabPillButton,
  design tokens (bg-app-*), demo-model fallback, sticky-header z-index fixes,
  and table ARIA roles re-layered onto olp's liquid-surface layout.

Backend (apps/api) — Library feature end-to-end:
- New library module (routes + service): files/templates folders + documents.
- renameTabularChat endpoint; documents/projects upload + query updates for
  library_kind/library_folder_id; prompts + systemWorkflows updates.
- Migration + schema for library_folders and documents library columns, with
  our hardened RLS/grants and magic-byte upload validation.

Shared packages:
- @mike/core: LibraryFolder, Document.library_kind/library_folder_id, isDocxFilename.
- @mike/api-client: library CRUD fns + renameTabularChat.

Verified: web/api/core/api-client typecheck + build clean; web lint 0 errors;
web 68, api 515, api-client 10 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@amal66 amal66 changed the title Open-source hardening & features: air-gap mode, extensibility, security, RAG, orgs, Word add-in, e2e & demo mode [DO NOT MERGE] Reference index: the amal66 fork, decomposed into 20 reviewable PRs Jul 17, 2026
…roducts#215/Open-Legal-Products#216)

The olp UI sync (b3166dd "sync olp UI as source of truth") and the liquid-
surface refinements reshaped several elements the Playwright suite asserts on.
None of it is a regression — the specs were describing the old shape. Six
specs across four files were failing on main; all six now pass.

  * The assistant/project chat input placeholder is "How can I help?", not
    "Ask a question about your documents..." (ChatInput.tsx / TRChatInput.tsx).
    Fixed in chat-management (rename/delete/project-assistant) and critical-path.
  * The project assistant empty state replaced the "+ Create New" text link
    with a PillButton reading "Create" (ProjectAssistantTable). critical-path
    and chat-management now target getByRole("button", { name: "Create" }).
  * The sidebar chat row's active marker is APP_SURFACE_ACTIVE_CLASS
    ("bg-app-surface-active"), not the old "bg-gray-200/60"; and the row
    wrapper is now h-8, not h-9 (SidebarChatItem.tsx). The rename and delete
    tests locate the active/first row accordingly.
  * The documents-toolbar folder-create button is now "Folder" (a
    TabPillButton wired to the root createFolderAction in ProjectDocumentsView),
    not "Add Subfolder"; it still opens the autofocused "Folder name" root input.
  * NewTRModal's footer submit and the tabular page's own CTA both read
    "Create", so the create-review spec now scopes to the modal submit
    (button[name="modalAction"][value="create-review"]) to avoid a strict-mode
    ambiguity.

Verified: full root Playwright suite green (27 passed) against the local demo
stack (Supabase + MinIO, demo model, e2e@mike.local).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CEguyEgXa9JjCciXCcVemC
@amal66 amal66 changed the title [DO NOT MERGE] Reference index: the amal66 fork, decomposed into 20 reviewable PRs [DO NOT MERGE] Reference index: the amal66 fork, decomposed into 25 reviewable PRs Jul 17, 2026
QA Runner and others added 2 commits July 17, 2026 10:49
Name the source PR and author (bmersereau, upstream Open-Legal-Products#76/Open-Legal-Products#77/Open-Legal-Products#78/Open-Legal-Products#145) in the
four files whose implementations were adapted from that work, matching the
convention the user_id-uuid migration already follows. PR-body credits landed
separately; these headers make the attribution travel with the code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CEguyEgXa9JjCciXCcVemC
generateChatTitle called completeText with the user's title_model directly, so
a keyless demo-mode chat 500'd on POST /chat/:id/generate-title the moment the
first reply finished — the streaming route applies resolveDemoFallback but the
title path never did. Move the helper to its own module (chat.routes re-exports
it) so chat.service can use it without an import cycle, and resolve the title
model through it. Found by the ladder QA browser pass; classified fork-level.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CEguyEgXa9JjCciXCcVemC
@amal66 amal66 changed the title [DO NOT MERGE] Reference index: the amal66 fork, decomposed into 25 reviewable PRs Reference index: the amal66 fork, decomposed into 25 reviewable PRs Jul 17, 2026
amal66 pushed a commit to amal66/mike that referenced this pull request Jul 20, 2026
Ported from the amal66 fork (see index Open-Legal-Products#205)
onto current main, adapted to this repo's backend/ layout
(apps/api/src/lib -> backend/src/lib), plus a v8 coverage ratchet.

Suites ported (51 new tests, verified locally):
- access.test.ts (7): owner/shared/private project access, doc access,
  review sharing, document-ID filtering. Dropped the fork's "org RBAC"
  describe block (7 cases) — org_id/org_members multi-tenancy and the
  role/canManage fields do not exist in this repo's access.ts.
- storage.test.ts (25): filename normalization/sanitization, RFC 5987
  encoding, Content-Disposition, storage key helpers. Dropped the fork's
  vi.mock of lib/env — this repo has no env module; storage reads
  process.env directly and the tested helpers are pure.
- userApiKeys.test.ts (10): normalizeApiKeyProvider + hasEnvApiKey.
  Added a beforeEach env clear so shell-exported API keys can't leak
  into assertions.
- chatTypes.test.ts (9): resolveDoc/resolveDocLabel, which live in
  lib/chat/types.ts here (the fork's lib/chatTools.ts equivalent).
  Dropped generateSpotlightNonce cases (2) — no such export here.

Suites dropped entirely (subject not present in this repo):
- upload.test.ts — tested hasMagicBytes; this repo's lib/upload.ts is
  only the multer middleware and exports no magic-byte checker.
- userSettings.test.ts — tested resolveTabularModel (fork-only keyed-
  provider fallback); this repo resolves tabular_model via
  resolveModel with a static default.

Coverage ratchet: vitest.config.mts adds v8 coverage over src/lib/**
with floors measured against this tree (2.58% stmts, 2.00% branches,
4.61% funcs, 2.58% lines -> floors 2/2/4/2). Full suite: 5 files,
63 tests passing (incl. the pre-existing 12 in downloadTokens.test.ts);
npm run test:coverage and npm run build both pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
willchen96 pushed a commit that referenced this pull request Jul 21, 2026
…checklist

Adds a Testing section documenting every suite the testing PR series
introduces (unit/integration via vitest, Playwright e2e, offline evals,
gated real-Supabase stack tests), the expectation that changes carry tests
at the lowest layer that catches the regression, and a PR template (ported
from the amal66 fork, #205) whose checklist asks how
the change was verified. Intended as the capstone of the series — the
commands it documents are introduced by the sibling test PRs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
willchen96 pushed a commit that referenced this pull request Jul 22, 2026
Ported from the amal66 fork (index: #205), adapted
to this repo's frontend/ layout and current component behavior. Adds the
jsdom + testing-library harness on top of the existing vitest setup:
vitest.config.mts (jsdom environment, @/ alias mirroring tsconfig paths,
dummy Supabase env for modules that build a client at import time) and
vitest.setup.ts (jest-dom matchers). New devDependencies: jsdom,
@testing-library/react, @testing-library/jest-dom,
@testing-library/user-event, @vitejs/plugin-react.

Ported suites (30 new tests):
- FileTypeIcon.test.tsx (11) — fileTypeKind mapping + icon rendering
- TRTable.test.tsx (1) — header/row render smoke test; the fork's ARIA
  role assertions (table/columnheader, "Tabular review" label) target
  fork-only markup — this repo's grid is div-based, so the test asserts
  rendered content instead
- button.test.tsx (4), pill-button.test.tsx (8), cite-button.test.tsx (3)
- useSmoothedReveal.test.ts (3) — passes against this repo's early-return
  snap behavior unchanged

Dropped (subjects don't exist here):
- HistoryDropdown.test.tsx — no tr-chat-panel/HistoryDropdown component
- applyAssistantStreamEvent.test.ts — no such module
- useProjectsQuery/useTabularReviewsQuery/useWorkflowsQuery tests —
  react-query is fork-only
- lib/toast.test.ts — no frontend/src/lib/toast.ts
- useAssistantChat.parsers.test.ts — the parser helpers exist inside
  useAssistantChat.ts but are not exported, and the fork's extracted
  module doesn't exist here

Verified: frontend npm test 38/38 passing (30 new + 8 pre-existing cn()
utils tests); npx tsc --noEmit clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pull Bot pushed a commit to admariner/mike that referenced this pull request Jul 23, 2026
Ports the backend route-level integration suites from the amal66 fork
(index: Open-Legal-Products#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>
@willchen96 willchen96 closed this Jul 25, 2026
eliziff pushed a commit to eliziff/Beaver that referenced this pull request Jul 29, 2026
Ported from the amal66 fork (see index Open-Legal-Products/mike#205)
onto current main, adapted to this repo's backend/ layout
(apps/api/src/lib -> backend/src/lib), plus a v8 coverage ratchet.

Suites ported (51 new tests, verified locally):
- access.test.ts (7): owner/shared/private project access, doc access,
  review sharing, document-ID filtering. Dropped the fork's "org RBAC"
  describe block (7 cases) — org_id/org_members multi-tenancy and the
  role/canManage fields do not exist in this repo's access.ts.
- storage.test.ts (25): filename normalization/sanitization, RFC 5987
  encoding, Content-Disposition, storage key helpers. Dropped the fork's
  vi.mock of lib/env — this repo has no env module; storage reads
  process.env directly and the tested helpers are pure.
- userApiKeys.test.ts (10): normalizeApiKeyProvider + hasEnvApiKey.
  Added a beforeEach env clear so shell-exported API keys can't leak
  into assertions.
- chatTypes.test.ts (9): resolveDoc/resolveDocLabel, which live in
  lib/chat/types.ts here (the fork's lib/chatTools.ts equivalent).
  Dropped generateSpotlightNonce cases (2) — no such export here.

Suites dropped entirely (subject not present in this repo):
- upload.test.ts — tested hasMagicBytes; this repo's lib/upload.ts is
  only the multer middleware and exports no magic-byte checker.
- userSettings.test.ts — tested resolveTabularModel (fork-only keyed-
  provider fallback); this repo resolves tabular_model via
  resolveModel with a static default.

Coverage ratchet: vitest.config.mts adds v8 coverage over src/lib/**
with floors measured against this tree (2.58% stmts, 2.00% branches,
4.61% funcs, 2.58% lines -> floors 2/2/4/2). Full suite: 5 files,
63 tests passing (incl. the pre-existing 12 in downloadTokens.test.ts);
npm run test:coverage and npm run build both pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
eliziff pushed a commit to eliziff/Beaver that referenced this pull request Jul 29, 2026
…checklist

Adds a Testing section documenting every suite the testing PR series
introduces (unit/integration via vitest, Playwright e2e, offline evals,
gated real-Supabase stack tests), the expectation that changes carry tests
at the lowest layer that catches the regression, and a PR template (ported
from the amal66 fork, Open-Legal-Products/mike#205) whose checklist asks how
the change was verified. Intended as the capstone of the series — the
commands it documents are introduced by the sibling test PRs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
eliziff pushed a commit to eliziff/Beaver that referenced this pull request Jul 29, 2026
Ported from the amal66 fork (index: Open-Legal-Products/mike#205), adapted
to this repo's frontend/ layout and current component behavior. Adds the
jsdom + testing-library harness on top of the existing vitest setup:
vitest.config.mts (jsdom environment, @/ alias mirroring tsconfig paths,
dummy Supabase env for modules that build a client at import time) and
vitest.setup.ts (jest-dom matchers). New devDependencies: jsdom,
@testing-library/react, @testing-library/jest-dom,
@testing-library/user-event, @vitejs/plugin-react.

Ported suites (30 new tests):
- FileTypeIcon.test.tsx (11) — fileTypeKind mapping + icon rendering
- TRTable.test.tsx (1) — header/row render smoke test; the fork's ARIA
  role assertions (table/columnheader, "Tabular review" label) target
  fork-only markup — this repo's grid is div-based, so the test asserts
  rendered content instead
- button.test.tsx (4), pill-button.test.tsx (8), cite-button.test.tsx (3)
- useSmoothedReveal.test.ts (3) — passes against this repo's early-return
  snap behavior unchanged

Dropped (subjects don't exist here):
- HistoryDropdown.test.tsx — no tr-chat-panel/HistoryDropdown component
- applyAssistantStreamEvent.test.ts — no such module
- useProjectsQuery/useTabularReviewsQuery/useWorkflowsQuery tests —
  react-query is fork-only
- lib/toast.test.ts — no frontend/src/lib/toast.ts
- useAssistantChat.parsers.test.ts — the parser helpers exist inside
  useAssistantChat.ts but are not exported, and the fork's extracted
  module doesn't exist here

Verified: frontend npm test 38/38 passing (30 new + 8 pre-existing cn()
utils tests); npx tsc --noEmit clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
eliziff pushed a commit to eliziff/Beaver that referenced this pull request Jul 29, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants