Reference index: the amal66 fork, decomposed into 25 reviewable PRs - #205
Closed
amal66 wants to merge 197 commits into
Closed
Reference index: the amal66 fork, decomposed into 25 reviewable PRs#205amal66 wants to merge 197 commits into
amal66 wants to merge 197 commits into
Conversation
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.
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>
…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
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
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>
This was referenced Jul 20, 2026
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>
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
main(branchupstream-mainon amal66/mike), in this repo's own layout (backend/+frontend/) — so every diff reads exactly as it would arrive here;Recommended merge order
Every row below is an independent diff against
upstream-mainand 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:backend/src/routes/*.tsfiles into 41backend/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 / #48and#40 → #41— a stacked row needs its base merged first. The only routine friction is lockfile churn: rows that add a dependency touchbackend/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)
Security pack (one topic per PR)
Reliability & interchange
.mikeworkflow.jsonexport/import with optional language/jurisdictions metadata — a UK pack isn't a US pack (feeds the SKILL.md workflows direction)Extensibility & local inference ("files never leave the building")
ENABLE_OLLAMAis set (stacks on #27)AIRGAPPED=trueis a hard kill switchArchitecture (each opens with a design doc — read the ADR before the diff)
search_documentstool, inside the firm's own database (stacks on #40)Clients & end-to-end proof
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