# MikeOSS Legal AI

## MikeOSS Legal AI

Drop-in cryptographic verification for [Mike](https://github.com/willchen96/mike), the open-source legal AI assistant by [Will Chen](https://github.com/willchen96). Every assistant response is checked against a plain-English policy compiled to SMT-LIB before it reaches the user. The proof is referenced by a `proof_id` persisted on the message row and surfaced as a "Verified" badge that any third party can independently re-verify.

> **Status.** This page describes the Mike + Preflight integration as designed. Deployed systems are the source of truth: Preflight's API at `api.icme.io` and Mike upstream at `github.com/willchen96/mike`. If anything here conflicts with the deployed system, the deployed system wins.

#### The verification gap in legal AI

Legal AI is the canonical "high downside, low margin for error" use case, and the guardrails that ship with it solve only half the problem. Two things have to be true, and today neither is.

**Enforcement has to be deterministic.** LLM-as-judge guardrails are probabilistic. A second model reads the first model's output and decides whether it looks compliant. That is pattern matching, not enforcement. It can be jailbroken, it drifts between model versions, and it has no ground truth. Preflight compiles each plain-English policy to SMT-LIB and discharges it through the Z3 SMT solver. The verdict is mathematical, not stylistic, and the same input always yields the same answer.

**The verdict has to be independently checkable.** Even a perfectly enforced policy is worth little if a regulator, opposing counsel, or auditor has to take the firm's word for it. Today they would need access to the firm's logs, infrastructure, and the original model. Preflight emits a `proof_id` with every verdict, referencing a zero-knowledge proof. A zero-knowledge proof is independently and repeatedly verifiable by anyone who holds it, without re-running the check: a regulator, opposing counsel, or auditor can confirm the verdict with no Mike access, no firm credentials, and no model access.

Deterministic enforcement makes the guardrail trustworthy. Third-party verifiability makes that trust transferable.

#### How Preflight closes it

```
user query
   │
   ▼
[ Preflight middleware ] ──▶ checkIt(action, policy) ──▶ SAT / UNSAT / ERROR
   │                                                         │
   ▼                                                         ▼
LLM call                                          proof_id + policy_hash
   │                                              persisted on chat_messages row
   ▼
assistant response  ──▶  UI badge linking to icme.io/proofs/<proof_id>
```

Three stages:

1. **Extract.** The proposed assistant action (matter, input, intended tool) is extracted from the request.
2. **Verify.** Preflight checks the action against the firm's compiled policy via `POST /v1/checkIt` and returns `result` (`SAT` or `UNSAT`), a `proof_id`, and a `policy_hash`.
3. **Persist.** The `proof_id` and `policy_hash` are written to new columns on `chat_messages` and rendered as a re-verifiable badge in the UI.

#### How verification works

Three independent paths check each action against the same compiled policy. OxiZ, a local extraction model, maps the action text to the policy's SMT variables. Automated Reasoning independently translates the raw action text to formal logic and checks it against the rules. Z3, the SMT solver, evaluates the extracted values. The system fails closed: any UNSAT from any path blocks the action. When Automated Reasoning returns `TRANSLATION_AMBIGUOUS`, the action can still clear if OxiZ and Z3 both confirm SAT.

Every decision is sealed into a zero-knowledge proof by JOLT, ICME's adaptation of the JOLT zkVM, wrapping the SMT verification pipeline. The proof generates in the background (typically 30 to 60 seconds) and is retrievable via `GET /v1/proof/{id}`. Anyone can verify it against `/v1/verifyProof` with no API key, learning only that the verdict was correctly computed against the compiled policy version named by `policy_hash`.

> **A note on JOLT Atlas.** ICME is developing JOLT Atlas, a separate zkML framework that will add cryptographic proofs for the AI extraction step itself. Today's proofs are produced by the JOLT zkVM and cover the SMT verification. JOLT Atlas is under active development and does not power production verification yet.

#### What this integration ships

The `preflight-mike` repository ships four files plus a one-shot `git am` patch:

| File                                       | Drops into Mike at                                        |
| ------------------------------------------ | --------------------------------------------------------- |
| `backend/lib/preflight.ts`                 | `backend/src/lib/preflight.ts`                            |
| `backend/middleware/preflight.ts`          | `backend/src/middleware/preflight.ts`                     |
| `backend/migrations/2026_01_preflight.sql` | `backend/migrations/2026_01_preflight.sql`                |
| `frontend/components/VerifiedBadge.tsx`    | `frontend/src/app/components/assistant/VerifiedBadge.tsx` |

The patch applies cleanly against Mike `main` and wires the middleware, DB columns, types, `mikeApi` mapping, and the badge into `AssistantMessage` in two commits.

#### Suggested policies

A starter policy set for a legal-AI deployment. Each compiles to SMT-LIB and is referenced by `policy_id` (UUID) at verification time.

| Policy             | Plain English                                                                  |
| ------------------ | ------------------------------------------------------------------------------ |
| Matter scope       | References must resolve to the current `project_id` only (privilege boundary). |
| Citation integrity | Every cited case, statute, or document must exist in the project's corpus.     |
| No specific advice | Jurisdictional outputs require a disclaimer and a cited authority.             |
| PII egress         | No SSNs, account numbers, or DOBs in output.                                   |
| Escalation scope   | Securities, healthcare, and M\&A questions must flag for human review.         |

#### Install

**One-shot patch (recommended)**

```bash
cd path/to/your/mike/checkout
git checkout -b feat/preflight
git am < /path/to/preflight-mike/mike.patch
```

**Manual drop-in**

Copy the four files into the paths in the table above, then follow [`INSTALL.md`](https://github.com/hshadab/preflight-mike/blob/main/INSTALL.md) for the wiring edits across `chat.ts`, `mikeApi.ts`, `types.ts`, `AssistantMessage.tsx`, and `ChatView.tsx`.

> **A note on shadow mode.** Shadow is the default and the recommended starting point. It calls Preflight, persists the verdict and `proof_id` on every message, but never blocks a response. Run shadow for a few days, review real verdicts, then flip to enforce.

#### Modes

`ICME_PREFLIGHT_ENFORCE` controls runtime behavior:

| Mode      | Behavior                                                                                 |
| --------- | ---------------------------------------------------------------------------------------- |
| `off`     | Middleware no-ops. Disable without removing code.                                        |
| `shadow`  | Calls Preflight, persists verdict and proof\_id on every message, never blocks. Default. |
| `enforce` | Returns HTTP 451 on `UNSAT` or verification error. Use in production.                    |

#### Express middleware

```ts
import { checkIt } from "../lib/preflight";

export function preflight(req, res, next) {
  const mode = process.env.ICME_PREFLIGHT_ENFORCE ?? "shadow";
  if (mode === "off") return next();

  const action = extractAction(req); // { matter, input, tool }
  const policyId = process.env.ICME_POLICY_ID;

  checkIt({ policy_id: policyId, action })
    .then(({ result, proof_id, policy_hash }) => {
      res.locals.preflight = { result, proof_id, policy_hash };
      if (mode === "enforce" && result === "UNSAT") {
        return res.status(451).json({ error: "policy_violation", proof_id });
      }
      next();
    })
    .catch((err) => {
      res.locals.preflight = { error: err.message };
      if (mode === "enforce") return res.status(451).json({ error: "verification_failed" });
      next();
    });
}
```

The middleware writes the Preflight result to `res.locals.preflight` so the chat handler can persist `proof_id` and `policy_hash` on the new `chat_messages` columns when it inserts the assistant message.

#### Database migration

```sql
-- backend/migrations/2026_01_preflight.sql
alter table public.chat_messages
  add column if not exists preflight_proof_id        text,
  add column if not exists preflight_result          text,
  add column if not exists preflight_policy_id        text,
  add column if not exists preflight_policy_hash      text;

create index if not exists idx_chat_messages_preflight_proof
  on public.chat_messages (preflight_proof_id);
```

#### API reference

| Endpoint          | Method | Purpose                                                                         |
| ----------------- | ------ | ------------------------------------------------------------------------------- |
| `/v1/checkIt`     | POST   | Verify an action against a policy. Returns `result`, `proof_id`, `policy_hash`. |
| `/v1/proof/{id}`  | GET    | Retrieve the zero-knowledge proof once generation completes (30 to 60 seconds). |
| `/v1/verifyProof` | POST   | Public re-verification. No firm credentials required.                           |

Sample `/v1/checkIt` response:

```json
{
  "result":      "SAT",
  "detail":      "Action complies with policy.",
  "proof_id":    "2e45c585-b7ec-4159-9cec-b3977fbcbbdc",
  "policy_id":   "8c2a4f9d-1b3e-4a7c-9d5f-2e8b1c4f7a3d",
  "policy_hash": "60c79bbc4f8ac087de1110fa0e347292f35b6d2943a2a4ccd18ae991a5d64418",
  "claimed_result": "SAT"
}
```

Sample `/v1/verifyProof` response (public, no API key):

```json
{
  "valid":          true,
  "verify_ms":      406,
  "policy_hash":    "60c79bbc4f8ac087de1110fa0e347292f35b6d2943a2a4ccd18ae991a5d64418",
  "claimed_result": "SAT",
  "used":           true,
  "proof_bytes_len": 92986,
  "trace_length":   524288,
  "created_at":     "2026-05-09T00:11:20.880850Z"
}
```

#### Verified badge

```tsx
export function VerifiedBadge({ proofId }: { proofId?: string }) {
  if (!proofId) return null;
  return (
    <a
      href={`https://icme.io/proofs/${proofId}`}
      target="_blank"
      rel="noreferrer"
      className="inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 border border-emerald-200"
    >
      ✓ Verified
    </a>
  );
}
```

Rendered next to each `AssistantMessage`. The badge links to a third-party verification page; no Mike credentials are needed to re-check the proof. Note that the proof generates in the background, so the badge may link to a proof that is still being produced for the first 30 to 60 seconds after a message.

#### What this integration does not do

* Does not replace Mike's citation extraction or document parsing.
* Does not modify Mike's model routing or per-user API key handling.
* Does not store, proxy, or have visibility into the prompt or response body. Only the structured action and the verdict.
* Does not run the LLM.
* Does not require schema changes outside `chat_messages`.

#### Privacy, privilege, and what the verifier sees

In a legal-AI deployment, the most sensitive object is often not the prompt or the response. It is the policy itself. Firms encode work product into their guardrail policies: conflicts watchlists, jurisdictional disclaimers, partner sign-off thresholds, engagement-scope caps, counterparties on a litigation watchlist. Disclosing that policy to a regulator, opposing counsel, or a client during an audit is itself a confidentiality concern, and in some jurisdictions a potential privilege waiver.

Preflight's privacy properties are shaped around this.

| Property                            | What stays private                                  | From whom                                                       |
| ----------------------------------- | --------------------------------------------------- | --------------------------------------------------------------- |
| Policy privacy                      | The policy text and the specific rule that fired    | The user, the LLM, the auditor, opposing counsel, the regulator |
| Action privacy at verification time | The prompt, the response, the matter, the documents | Any third party re-checking the proof from a `proof_id`         |
| Versioned binding                   | Which compiled policy version decided this message  | Nobody. The `policy_hash` is public, the policy text is not     |

The public `/v1/verifyProof` receipt contains `valid`, `verify_ms`, `policy_hash`, `claimed_result`, and proof metadata. It does not contain the prompt, the response, the matter name, the document text, or any rule of the policy. A regulator or opposing counsel verifying a proof learns that a specific compiled policy version decided a specific message. They do not learn what the policy says, what the message was about, or which matter it touched.

The `policy_hash` is the legal-tech-specific property. Firms revise policies over time. When a regulator later asks "what guardrails were in force on the date of this advice," the answer is the compiled policy version hash bound to every proof issued that day. The hash is public; the policy is not.

**Honest scope**

Preflight's cryptographic guarantees protect *downstream verifiers*: the regulator, the client, opposing counsel, the state bar. They do not anonymize the submission path:

* ICME's server sees the plain-English policy at the time the firm compiles it via `/v1/makeRules`.
* ICME's server sees the structured action at the time Mike calls `/v1/checkIt` to check it.
* Mike itself, and the firm's chosen model vendor (Claude, Gemini, or OpenAI via the firm's API keys), sees the prompt and the response in cleartext as usual. Preflight does not change that surface.

For firms that need cryptographic inference privacy on top, including encrypted prompts, hardware-attested inference, and model-vendor blindness, Preflight composes cleanly with privacy-preserving inference providers. The inference layer keeps the prompt private from the model vendor; Preflight keeps the policy private from everyone downstream of enforcement.

#### Compliance alignment

| Regime                             | Relevance                                                                                                                                                            |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ABA Model Rule 1.6                 | Confidentiality. Policy privacy and non-disclosing receipts mean firm-side confidentiality is not waived during third-party audit.                                   |
| ABA Model Rule 5.3                 | Supervision of nonlawyer assistants (AI). Each proof receipt is the supervision artifact.                                                                            |
| ABA Model Rule 1.1 cmt 8           | Technological competence. Formally verified guardrails, not LLM-judge pattern matching.                                                                              |
| ABA Formal Opinion 512 (July 2024) | Competent and confidential use of GAI; verifiable enforcement is in scope.                                                                                           |
| Privilege and work product         | The policy itself may be work product. Preflight never returns the compiled policy to any caller; the `policy_hash` proves enforcement without disclosing the rules. |
| State bar AI guidance (CA, FL, NY) | Verifiable enforcement records satisfy emerging "demonstrable supervision" expectations without requiring the firm to surrender its policy.                          |

The proof receipt is the audit artifact. A state bar, opposing counsel, or client can verify a `proof_id` at icme.io and confirm the verdict without firm access, the original model, the original prompt, or sight of the policy itself.

#### Try it yourself

| Resource                      | Link                                                                                                                               |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Standalone UI demo (no setup) | [github.com/hshadab/preflight-mike/blob/main/demo/index.html](https://github.com/hshadab/preflight-mike/blob/main/demo/index.html) |
| Drop-in repo (patch + files)  | [github.com/hshadab/preflight-mike](https://github.com/hshadab/preflight-mike)                                                     |
| Patched reference fork        | [github.com/hshadab/mikeoss](https://github.com/hshadab/mikeoss) on `feat/icme-preflight-verification`                             |
| Mike upstream                 | [github.com/willchen96/mike](https://github.com/willchen96/mike)                                                                   |
| Preflight quickstart          | [docs.icme.io](https://docs.icme.io/)                                                                                              |

#### Credits

* [Will Chen](https://github.com/willchen96) for building Mike as open source.
* Built by ICME for the Mike community. AGPL-3.0 on Mike's side, MIT on the integration glue.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.icme.io/documentation/privacy-and-data-security/mikeoss-legal-ai.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
