Skip to content
decosa
LiveHostedSelf-hostSelf-host first for real data

Investigate a Reg E dispute

An investigation file per dispute: every Reg E deadline worked out with its rule, the notice's required details quoted, and the results letter checked.

Held-out test0.956 (43/45)Missing details in consumer dispute notices flagged (held-out test)
On production38 smedian on production (2026-09-26); slower when the service is busy
List price~$0.57 per 100 filesmeasured, at list price

Built on: Grounding, Typed judgment, Signed record

Loading the tool…

Use it your way

Use it from your codeThe hosted API with your key, and prompts to paste into a coding agent
Self-host · your GPUs · recommended

Run it yourself, on request

  • The same open models and app, on 1x RTX PRO 6000 (96 GB) for Qwen3.8-27B; the clocks, the checklist and the signed record need no GPU.
  • Data never leaves your machines, and there are no Decosa charges.
  • One prompt for Claude Code or Codex assembles the whole stack.
  • Early access: the container images are not public yet and the source needs access; the prompt says how to ask.
Hosted · by Decosa

Get an API key

  • Call the reg e dispute investigation file API from your own code in minutes.
  • Every model answer carries a signed receipt.
  • Synthetic, public or test data only: real confidential data belongs on your own hardware.

Build with it

Paste one of these into Claude Code, Codex or another coding agent. The first wires your project to the hosted API with your DECOSA_API_KEY. The second pulls our containers and runs the same stack on your own GPU, with no Decosa charges.

Base URL
https://api.decosa.ai
Auth
Authorization: Bearer $DECOSA_API_KEY (or a demo session token)
Tool id
reg-e-dispute-file

Use the hosted API

# Decosa Reg E dispute investigation file: use the hosted API

You are wiring Decosa's Reg E dispute file into this project. It takes a consumer's notice of an electronic fund transfer
error, the account's transactions as CSV and the investigation (notes, events, the investigator's determination and
results letter), and returns an investigation file with a signed record. Every model call has a signed receipt. Use only
what is listed below; if you need something else, stop and ask me.

The file has:
- every Regulation E clock computed in code with the rule cited (12 CFR 1005.11; 1005.18(e) for prepaid accounts;
  1005.33 for remittances), each `met`, `missed`, `overdue`, `open`, `not_needed`, `unknown` or `late_notice`, and a timeline;
- the notice's required elements (name, account, why, and to the extent possible type, date and amount), each quoted;
- a checklist of gaps, and for a `no_error` or `different_error` finding a check that the letter explains the findings for
  this case, notes the right to request the documents relied on, and that the documents are listed;
- a file status: `open` (no determination yet), `gaps` or `complete`.

- Base URL: `https://api.decosa.ai`
- Health check: `GET https://api.decosa.ai/healthz`.
- **Hosted use is for synthetic disputes only.** Consumer notices and account data are nonpublic personal information:
  real disputes belong on a self-hosted box (see the self-host prompt). Say so wherever this is wired in.
- **It never decides a claim.** The determination comes only from `investigation.determination`, entered by a named
  investigator. Never fill it in from the tool's output, and never auto-deny.

## Auth: API key (or a demo session)
1. Preferred: an API key (`dk_…`) from "Get an API key" on the tool page. Keep it in an environment variable,
   `DECOSA_API_KEY`, never in code. Send `Authorization: Bearer $DECOSA_API_KEY`.
2. Without a key: `POST https://api.decosa.ai/demo/session` with `{"vertical": "reg-e-dispute-file"}` returns `{"token", "expires_at", "budget"}`.
   - The demo allows a limited number of sessions per network per hour (the current limits are in `demo_sessions` of GET /healthz) and a token allowance per session (the `budget` in the session response).
   - Over a limit you get HTTP 429 with `Retry-After`.
   - A demo token runs one file at a time (409 otherwise).
3. A file with notes and a letter needs about 5,500 generated tokens left in the budget before it starts (402 otherwise);
   it usually uses fewer, and only what it uses is charged.

## Endpoints
- `POST /rege/file` (token). Body: `{"regime"?: "account"|"prepaid"|"remittance", "notice": {"text", "received": "YYYY-MM-DD", "channel"?: "oral"|"written", "written_confirmation"?: {"required", "told_consumer", "received"}, "extenuating_circumstances"?}, "account"?: {"first_deposit"?, "reg_t"?, "ref"?}, "transactions_csv"?, "disputed_ids"?, "investigation"?: {"investigator"?, "notes"?, "events"?: [{"kind", "date", "amount"?, "note"?}], "documents_relied_on"?: [...], "letter"?, "determination"?: {"outcome": "error_as_alleged"|"different_error"|"no_error", "by", "date"}}, "closed_days"?: [...], "today"?, "title"?}` or `{"sample_id": "..."}`.
  - CSV columns: `id,date,amount,type,description` required; `posted,statement_sent,country,counterparty,available_date,disputed`
    optional. Negative amounts are debits. `statement_sent` may be `pending`. Types: `pos`, `card_not_present`, `atm`,
    `p2p`, `ach`, `bill_pay`, `transfer`, `remittance`, `deposit`, `other`.
  - Event kinds: `investigation_started`, `written_confirmation_received`, `provisional_credit`,
    `provisional_credit_notice`, `determination`, `report_sent`, `correction`, `provisional_credit_debited`,
    `debit_notice`, `documents_requested`, `documents_sent`.
  - Limits: a notice of 20,000 characters, notes of 20,000, a letter of 12,000, 2,000 CSV rows, 25 disputed transfers,
    320 KB of JSON.
  - The JSON response has `file_status` (`{status, why, gaps, checks, cannot_close?}`), `determination` (exactly as
    entered, `actor: "human"`), `clocks` (`{rows: [{id, what, due, actual, status, arithmetic, rules}], timeline, flags,
    triggers, conventions}`), `checklist` (`[{id, what, status, detail, rules}]`), `notice` (elements with quotes),
    `coverage` (rule text for questions only the investigator can answer), `letter`, `letter_sentences`, `facts_on_file`,
    `file_md`, `record`, `record_check`, `receipts`, `steps` and `note`.
  - With `Accept: text/event-stream` (or `"stream": true`), the events are `ready`, a `receipt` per model call, `notice`,
    `transfers`, `notes`, `letter`, a `sentence` per letter sentence, `clocks`, `checklist`, then `result`, `budget` and `done`.
- `POST /rege/clocks` (no token, no model) takes the same body without the notice text and returns the clocks alone.
- `POST /record/verify` (no token) `{"record": {...}}` returns `{ok, summary, checks, first_bad}`.
- `GET /rege/info`, `GET /rege/samples` and `GET /attest/signing-key` need no token.

## Example: build a file and list what is missing (Python, `pip install httpx`)
```python
import httpx, json, os
API = "https://api.decosa.ai"
H = {"Authorization": f"Bearer {os.environ['DECOSA_API_KEY']}"}
body = {"notice": {"text": open("notice.txt").read(), "received": "2026-09-15", "channel": "written"},
        "transactions_csv": open("transactions.csv").read(), "disputed_ids": ["T-1"],
        "investigation": json.load(open("investigation.json"))}   # notes, events, determination entered by a person, letter
r = httpx.post(f"{API}/rege/file", json=body, headers=H, timeout=600)
r.raise_for_status()
js = r.json()
print(js["file_status"]["status"], js["file_status"].get("cannot_close", ""))
for row in js["clocks"]["rows"]:
    print(f"{row['status']:>11}  {row['what']}  due {row['due']}")
for item in js["checklist"]:
    if item["status"] != "ok":
        print(f"{item['status']:>5}  {item['what']}: {item['detail']}")
open("reg-e-file.md", "w").write(js["file_md"])
json.dump(js["record"], open("reg-e-file.json", "w"))   # keep with the dispute for at least two years
```

Run it yourself (containers)

On request. The container images and the compose file aren’t public yet. Ask for self-host access and Decosa sends the registry (DECOSA_REGISTRY) and the compose file’s URL (DECOSA_COMPOSE_URL) these steps use. They are the steps we tested end to end on a fresh machine.

# Decosa Reg E dispute investigation file: run it yourself (containers)

You are setting up the Decosa Reg E dispute file on this machine, so consumer notices and account data never leave it.
It reads a notice of an electronic fund transfer error, the account's transactions (CSV) and the investigation notes,
events and results letter, and returns:
- every Regulation E clock computed in code with the rule cited, and a timeline;
- the notice's required elements, each quoted;
- a checklist of the file's gaps, including whether a no-error letter explains the findings and notes the right to
  request the documents relied on;
- a file status (open, gaps or complete) and the investigator's determination exactly as entered.

It seals a signed record. Nothing is sent to Decosa's hosted API.

Status: the container images (${DECOSA_REGISTRY}/decosa-*) and the compose file are on request while self-host is in early access (not on a public registry yet): ask at https://decosa.ai/contact?topic=self-host, and Decosa sends the registry as DECOSA_REGISTRY, the compose file URL as DECOSA_COMPOSE_URL, and pull access. If a pull fails with
"not found", "denied" or "unauthorized", stop and tell me. Do not substitute other images.

Ask me before any command that needs sudo, and show me the command first.

## Step 0: set up with a coding agent, rehearse on mock data, then go private

This prompt is for a coding agent running on the machine that will host the service. We recommend Claude Code with
Claude Opus 5.5; any capable coding agent works. Work in this order:

1. Set up on mock data only. During the whole setup you (the agent) work with the synthetic sample bundle below and
   nothing else. Do not ask me for real data, and do not open, read, list or copy files that hold real data, even to
   "test with something realistic".
2. Rehearse. When the steps below are done and the service is healthy, fetch the mock-data bundle for this tool,
   https://decosa.ai/samples/reg-e-dispute-file.zip (6 KB, 14 checks, synthetic or openly licensed: see `licence` in expected.json),
   show me what is in it, and run the rehearsal against the local API:
   `docker compose exec api python scripts/rehearse.py reg-e-dispute-file` (the api image carries the same bundle under /app/rehearsal/reg-e-dispute-file/;
   with no key set, the script asks the local API for a short demo token). From a decosa-api checkout instead:
   `python scripts/rehearse.py reg-e-dispute-file --bundle reg-e-dispute-file.zip --base-url http://127.0.0.1:<PORT>`.
   It sends the mock inputs to the local API and prints PASS or FAIL for each expected property (for example: "the provisional credit notice is due two business days after the credit (4 Sep 2026) and came late (no model)", "the May charge was reported more than 60 days after its statement", "a debit card online purchase gets the 90-day period"). Show me
   the full output. Every check must pass. If one fails, fix the install and run it again; never edit `expected.json`
   to make a check pass.
3. Stop there. Once the rehearsal passes, tell me, and I will run my own data against the local API myself, on this
   machine.

For the person running this: a coding agent that runs in the cloud sees everything in its context, including files it
reads, command output and anything pasted into the chat. Keep real data out of the chat and out of anything the agent
can read. Switch to your own data only after the rehearsal has passed and the agent's work is done.

## Steps
1. Docker: if `docker compose version` fails, install Docker Engine and the compose plugin using Docker's official
   instructions for this distribution (docs.docker.com/engine/install). Install the NVIDIA container toolkit, then check
   `docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smi`.
2. Fetch the compose file:
   `mkdir -p ~/decosa && cd ~/decosa && curl -fsSL "${DECOSA_COMPOSE_URL}" -o compose.yaml`
   Read it. Keep the `llm` service (Qwen3.8-27B on vLLM) and the `api` service. On the `api` service:
   - set `DECOSA_LLM_ROUTE=direct`, `DECOSA_LLM_URL=http://llm:8000/v1` and `DECOSA_LLM_MODEL=qwen3.8-27b`;
   - keep its data on a named volume;
   - bind every port to 127.0.0.1.
3. Pull and start: `docker compose pull && docker compose up -d`. Wait for the `llm` health check. The first start
   downloads about 20 GB of weights.
4. Check: `curl -fsS http://127.0.0.1:<PORT>/rege/info` lists every rule with its citation, link and exact words.
   `GET /attest/signing-key` shows this box's public key. Show me the key: it is what an examiner pins to verify my files.
5. Smoke test:
   - `POST /rege/clocks {"sample_id":"cnp-generic-denial"}` needs no model: `provisional_credit_notice` should be `missed`
     (due `2026-09-04`) and `notice:T-0512` `late_notice`.
   - Get a token with `POST /demo/session {"vertical":"reg-e-dispute-file"}`, then send
     `POST /rege/file {"sample_id": "cnp-generic-denial"}`. Expect `file_status.status` `gaps` with `cannot_close`, the
     determination `no_error` by Jordan Okafor exactly as entered, and every receipt `attested`.
   - `{"sample_id": "p2p-takeover-open"}` should come back `open` with no determination.
   - `POST /record/verify {"record": <record>}` should give `ok: true`.
6. Report back: the public key and key id, the smoke-test results, and how long each file took.

Consumer notices and account data are nonpublic personal information. The tool never decides a claim: a named
investigator does. It is not legal advice, and it does not cover card-network rules, Regulation Z or state law. Reg E
business days are your institution's: list your closed days in `closed_days`.

Off by default. Joining as a provider serves other people's requests on this GPU. Never do it on a box that holds
consumer account data. If I ask for it later, follow the Provide page instead of improvising.
Run it on your own hardwareWhat it needs, and the prompt that sets it up

Run it on your own GPU

Same app, same pinned models, your hardware. Nothing goes to our servers and there are no Decosa charges.

  • CPU only, 64 GB RAMDoesn't fit

    Qwen3.8-27B (NVIDIA NVFP4) needs a GPU.

  • GeForce RTX 4090standard tierRuns

    The standard tier fits with changes: Replace Qwen3.8-27B (NVIDIA NVFP4) with A community 4-bit build of Qwen3.8-27B (AWQ or GGUF). This build is NVIDIA NVFP4, which needs a Blackwell GPU. (Memory is an estimate.)

  • GeForce RTX 5090standard tierRuns

    The standard tier fits with changes: Qwen3.8-27B (NVIDIA NVFP4): run it at its smallest setting (about 28 GB instead of 57.6 GB), with a shorter context and fewer parallel sessions.

  • 2x GeForce RTX 5090standard tierRuns

    The standard tier fits with changes: Split the language model across the GPUs with tensor parallelism (vLLM --tensor-parallel-size).

  • L40Sstandard tierRuns

    The standard tier fits with changes: Replace Qwen3.8-27B (NVIDIA NVFP4) with Qwen3.8-27B official FP8. This build is NVIDIA NVFP4, which needs a Blackwell GPU.

  • H100 80 GB (SXM)standard tierRuns

    The standard tier fits with changes: Replace Qwen3.8-27B (NVIDIA NVFP4) with Qwen3.8-27B official FP8. This build is NVIDIA NVFP4, which needs a Blackwell GPU.

  • RTX PRO 6000 Blackwell 96 GBstandard tierRuns

    The standard tier fits (57.6 of 96 GB).

  • 2x RTX PRO 6000 Blackwell 96 GBbest tierRuns

    The standard tier fits (57.6 of 192 GB). The best tier fits too.

  • Apple M3 Ultra (Mac Studio), 96 GBstandard tierRuns

    The standard tier fits with changes: Replace Qwen3.8-27B (NVIDIA NVFP4) with Qwen3.8-27B MLX 4-bit. MLX build for Apple Silicon.

  • Apple M5 Max, 64 GBstandard tierRuns

    The standard tier fits with changes: Replace Qwen3.8-27B (NVIDIA NVFP4) with Qwen3.8-27B MLX 4-bit. MLX build for Apple Silicon.

Memory per component comes from measured footprints, the tool's stack.json, or an estimate from its parameter count, and each is labelled that way below. Only an RTX PRO 6000 and an M3 Ultra Mac Studio have actually been run.

On request. The container images and the compose file aren’t public yet. Ask for self-host access and Decosa sends the registry (DECOSA_REGISTRY) and the compose file’s URL (DECOSA_COMPOSE_URL) these steps use. They are the steps we tested end to end on a fresh machine.

  1. 1

    Check the GPU, Docker and the NVIDIA Container Toolkit

    The driver must see the GPU, and Docker must be able to pass it into a container.

    nvidia-smi
    docker compose version
    docker run --rm --gpus all ubuntu nvidia-smi
  2. 2

    Fetch the compose file

    One file describes the API and the language model as services.

    mkdir -p ~/decosa && cd ~/decosa
    curl -fsSL "${DECOSA_COMPOSE_URL}" -o compose.yaml
  3. 3

    Pull and start

    The first start downloads pinned model weights, tens of gigabytes.

    docker compose pull
    docker compose up -d
  4. 4

    Check health

    Wait until the API reports ok with the language model loaded. Then point your app at the local base URL.

    curl -fsS http://localhost:<PORT>/healthz
    # {"ok": true, "llm": true, ...}
    curl -fsS -X POST http://localhost:<PORT>/demo/session \
      -H 'Content-Type: application/json' -d '{"vertical":"reg-e-dispute-file"}'

Set up with a coding agent, rehearse on mock data, then go private

  1. Set up with a coding agent. Paste the self-host prompt into a coding agent on the machine that will run the service. We recommend Claude Code with Claude Opus 5.5; any capable coding agent works.
  2. Rehearse on mock data. The agent runs the tool on a bundle of synthetic inputs and checks each answer against the bundle's expected.json. Every check must print PASS.
  3. Go private. Only then do you run your own data against the local API, yourself, on that machine. Never give the agent real data during setup: a coding agent that runs in the cloud sees everything in its context, so keep real data out of the chat and out of the files it reads.
Rehearsal command
docker compose exec api python scripts/rehearse.py reg-e-dispute-file

Download the mock-data bundle (6 KB, 14 checks)expected.json

Two synthetic Regulation E disputes. The first: two online debit card charges, one reported more than 60 days after its statement; provisional credit on time but its notice four business days late; a 'no error' letter with no facts, no right to request documents and no documents listed. The file must mark the late notice, the missed clock and each letter gap, refuse to call the file complete, and keep the investigator's determination exactly as entered. The second: a consumer tricked into sending a P2P payment; the file must show the coverage question (with 12 CFR 1005.2(m)) instead of answering it, the claim held for an affidavit, and the determination on business day 13 with no provisional credit. The signed file must verify, and fail once the determination in it is changed.

What the rehearsal checks
  • the provisional credit notice is due two business days after the credit (4 Sep 2026) and came late (no model)
  • the May charge was reported more than 60 days after its statement
  • a debit card online purchase gets the 90-day period
  • the generic 'no error' letter is marked as a gap
  • the missing right-to-documents sentence is marked as a gap
  • the file cannot be closed without the explanation and the documents relied on
  • the determination is exactly what the investigator entered
  • and it is recorded as a human decision
  • the signed file verifies
  • a file whose determination was changed no longer verifies
  • the scam case shows the coverage question instead of answering it
  • the determination on business day 13 without provisional credit is a missed clock
  • holding the claim for an affidavit is marked
  • every model call has a signed receipt

Licence: Synthetic cases (CC0): consumers, accounts, merchants, banks and investigators are invented (scripts/rege_cases.py). Part of decosa-api, AGPL-3.0-or-later.

Prompt for your coding agent

# Decosa Reg E dispute investigation file: run it yourself (containers)

You are setting up the Decosa Reg E dispute file on this machine, so consumer notices and account data never leave it.
It reads a notice of an electronic fund transfer error, the account's transactions (CSV) and the investigation notes,
events and results letter, and returns:
- every Regulation E clock computed in code with the rule cited, and a timeline;
- the notice's required elements, each quoted;
- a checklist of the file's gaps, including whether a no-error letter explains the findings and notes the right to
  request the documents relied on;
- a file status (open, gaps or complete) and the investigator's determination exactly as entered.

It seals a signed record. Nothing is sent to Decosa's hosted API.

Status: the container images (${DECOSA_REGISTRY}/decosa-*) and the compose file are on request while self-host is in early access (not on a public registry yet): ask at https://decosa.ai/contact?topic=self-host, and Decosa sends the registry as DECOSA_REGISTRY, the compose file URL as DECOSA_COMPOSE_URL, and pull access. If a pull fails with
"not found", "denied" or "unauthorized", stop and tell me. Do not substitute other images.

Ask me before any command that needs sudo, and show me the command first.

## Step 0: set up with a coding agent, rehearse on mock data, then go private

This prompt is for a coding agent running on the machine that will host the service. We recommend Claude Code with
Claude Opus 5.5; any capable coding agent works. Work in this order:

1. Set up on mock data only. During the whole setup you (the agent) work with the synthetic sample bundle below and
   nothing else. Do not ask me for real data, and do not open, read, list or copy files that hold real data, even to
   "test with something realistic".
2. Rehearse. When the steps below are done and the service is healthy, fetch the mock-data bundle for this tool,
   https://decosa.ai/samples/reg-e-dispute-file.zip (6 KB, 14 checks, synthetic or openly licensed: see `licence` in expected.json),
   show me what is in it, and run the rehearsal against the local API:
   `docker compose exec api python scripts/rehearse.py reg-e-dispute-file` (the api image carries the same bundle under /app/rehearsal/reg-e-dispute-file/;
   with no key set, the script asks the local API for a short demo token). From a decosa-api checkout instead:
   `python scripts/rehearse.py reg-e-dispute-file --bundle reg-e-dispute-file.zip --base-url http://127.0.0.1:<PORT>`.
   It sends the mock inputs to the local API and prints PASS or FAIL for each expected property (for example: "the provisional credit notice is due two business days after the credit (4 Sep 2026) and came late (no model)", "the May charge was reported more than 60 days after its statement", "a debit card online purchase gets the 90-day period"). Show me
   the full output. Every check must pass. If one fails, fix the install and run it again; never edit `expected.json`
   to make a check pass.
3. Stop there. Once the rehearsal passes, tell me, and I will run my own data against the local API myself, on this
   machine.

For the person running this: a coding agent that runs in the cloud sees everything in its context, including files it
reads, command output and anything pasted into the chat. Keep real data out of the chat and out of anything the agent
can read. Switch to your own data only after the rehearsal has passed and the agent's work is done.

## Steps
1. Docker: if `docker compose version` fails, install Docker Engine and the compose plugin using Docker's official
   instructions for this distribution (docs.docker.com/engine/install). Install the NVIDIA container toolkit, then check
   `docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smi`.
2. Fetch the compose file:
   `mkdir -p ~/decosa && cd ~/decosa && curl -fsSL "${DECOSA_COMPOSE_URL}" -o compose.yaml`
   Read it. Keep the `llm` service (Qwen3.8-27B on vLLM) and the `api` service. On the `api` service:
   - set `DECOSA_LLM_ROUTE=direct`, `DECOSA_LLM_URL=http://llm:8000/v1` and `DECOSA_LLM_MODEL=qwen3.8-27b`;
   - keep its data on a named volume;
   - bind every port to 127.0.0.1.
3. Pull and start: `docker compose pull && docker compose up -d`. Wait for the `llm` health check. The first start
   downloads about 20 GB of weights.
4. Check: `curl -fsS http://127.0.0.1:<PORT>/rege/info` lists every rule with its citation, link and exact words.
   `GET /attest/signing-key` shows this box's public key. Show me the key: it is what an examiner pins to verify my files.
5. Smoke test:
   - `POST /rege/clocks {"sample_id":"cnp-generic-denial"}` needs no model: `provisional_credit_notice` should be `missed`
     (due `2026-09-04`) and `notice:T-0512` `late_notice`.
   - Get a token with `POST /demo/session {"vertical":"reg-e-dispute-file"}`, then send
     `POST /rege/file {"sample_id": "cnp-generic-denial"}`. Expect `file_status.status` `gaps` with `cannot_close`, the
     determination `no_error` by Jordan Okafor exactly as entered, and every receipt `attested`.
   - `{"sample_id": "p2p-takeover-open"}` should come back `open` with no determination.
   - `POST /record/verify {"record": <record>}` should give `ok: true`.
6. Report back: the public key and key id, the smoke-test results, and how long each file took.

Consumer notices and account data are nonpublic personal information. The tool never decides a claim: a named
investigator does. It is not legal advice, and it does not cover card-network rules, Regulation Z or state law. Reg E
business days are your institution's: list your closed days in `closed_days`.

Off by default. Joining as a provider serves other people's requests on this GPU. Never do it on a box that holds
consumer account data. If I ask for it later, follow the Provide page instead of improvising.

Help me customise for my hardware

Pick your GPU or Mac, or enter its memory. You get the tier that fits, the model swaps it needs, measured speed where we have it, and a setup prompt with those choices written in.

Hardware

GeForce RTX 5090: 32 GB GDDR7, 1,792 GB/s, FP8 and NVFP4. NVIDIA product page

RunsReg E dispute investigation file on GeForce RTX 5090: use the Standard · the hosted demo, one 96 GB card tier

The standard tier fits with changes: Qwen3.8-27B (NVIDIA NVFP4): run it at its smallest setting (about 28 GB instead of 57.6 GB), with a shorter context and fewer parallel sessions.

Standard · the hosted demo, one 96 GB card: what changesuses estimates

  • Qwen3.8-27B (NVIDIA NVFP4): run it at its smallest setting (about 28 GB instead of 57.6 GB), with a shorter context and fewer parallel sessions.
Memory per component
  • Reads the consumer's notice: Qwen3.8-27B (NVIDIA NVFP4). ~57.6 GB (at least ~28 GB), weights 21.4 GB (from stack.json). Qwen3.8-27B NVFP4: Weights 19.9 GiB (21.4 GB), measured (field stack.json). The compose file gives the server 0.60 of a 96 GB card (57.6 GB) so the rest is FP8 KV cache for several sessions. The 28 GB minimum is an estimate: weights plus a short-context KV cache, which is why several stacks list a 32 GB RTX 5090 as 'estimate'. (stack.json lists 57 GB for this component.)

Expected speed

Not measured.

Not measured on this hardware. The only measured setups are an RTX PRO 6000 Blackwell and a Mac Studio M3 Ultra.

Setup prompt for this hardware

The self-host prompt for Reg E dispute investigation file, with a hardware plan for GeForce RTX 5090 added after Step 0. Loading the full prompt; until then it points your agent at the prompt's URL.

# Set up Reg E dispute investigation file on my hardware

Fetch https://decosa.ai/prompts/reg-e-dispute-file-selfhost.md and follow it (including Step 0: rehearse on mock data first), with the hardware plan below applied.

## Hardware plan for this machine (from https://decosa.ai/self-host/hardware?use=reg-e-dispute-file)

Target machine: GeForce RTX 5090 (32 GB of GPU memory; CUDA, FP8 and NVFP4).
Quality tier: Standard · the hosted demo, one 96 GB card (standard). Fit check: runs with changes, about 28 GB of 32 GB used; some memory numbers are estimates, not measurements.

First, check the machine: run `nvidia-smi` (or `rocm-smi`, or `sysctl hw.memsize` on a Mac) and confirm the GPUs and free memory match the line above. If they do not, stop and tell me before pulling anything.

Use these components (the setup below describes the standard tier; change it to match):
- Reads the consumer's notice: Qwen3.8-27B (NVIDIA NVFP4) (nvidia/Qwen3.8-27B-NVFP4), 57.6 GB. Change: Qwen3.8-27B (NVIDIA NVFP4): run it at its smallest setting (about 28 GB instead of 57.6 GB), with a shorter context and fewer parallel sessions.

GPU placement (set each service's device and its vLLM --gpu-memory-utilization to about the share shown):
- GPU 0: Qwen3.8-27B (NVIDIA NVFP4) ~28 GB (88%); about 4 GB left

During the rehearsal, watch GPU memory. If a model fails to load or runs out of memory, lower its --max-model-len and --max-num-seqs first, then its memory share, and tell me what you changed.

The stack's own component list and compose layout: https://decosa.ai/prompts/reg-e-dispute-file-assemble.md

The proof

How we tested itEval results and end-to-end checks, hosted and self-hosted, with dates

Verified end to end

Hosted: verified 26 Sep 2026 · measured 26 Sep 2026: · p50 38 s · ~$0.006 per run · 8 receipts

Loading the nightly status…

Self-host: verified 26 Sep 2026 · fresh clone of decosa-api into a clean directory on our server, api image built from docker/api/Dockerfile, compose api service with a named data volume, direct route, local signing; torn down after

Measured cost to run: about $0.57 per 100 files (hosted, 26 Sep 2026). Self-hosting is free: the code is open and the models are open-weight. You pay only for your own hardware and power.

The assembly prompt's smoke tests passed against the already-running local Qwen3.8-27B vLLM (network_mode host instead of the compose llm service): clocks as expected, cnp-generic-denial gaps with cannot_close in 18.6 s (8 attested receipts), p2p-scam-consumer-sent gaps with the consumer_sent coverage question, p2p-takeover-open open with no determination, record verified; the rehearsal bundle passed 14/14. Model-server startup was not re-run.

Known limits (4)
  • Hosted verification ran on the pre-release server (decosa-api the pre-release branch on our server, gateway route). The production API gets this vertical when the branch merges.
  • Measured on synthetic, templated notices and letters written by the building agent; not on a bank's real notices, notes or letter templates.
  • Federal rules only: no Regulation Z, card-network rules or state law. Business days default to the Federal Reserve Banks' calendar.
  • The notice, notes and letter are read by a model and can be wrong in both directions; the clocks depend on the dates you send (statement dates in the CSV).

Eval results, nightly checks and cost per runVerify a run

How it's builtThe steps, the models and what each one checks
Self-host · your GPUs · recommended

Run it yourself, on request

  • The same open models and app, on 1x RTX PRO 6000 (96 GB) for Qwen3.8-27B; the clocks, the checklist and the signed record need no GPU.
  • Data never leaves your machines, and there are no Decosa charges.
  • One prompt for Claude Code or Codex assembles the whole stack.
  • Early access: the container images are not public yet and the source needs access; the prompt says how to ask.
Hosted · by Decosa

Get an API key

  • Call the reg e dispute investigation file API from your own code in minutes.
  • Every model answer carries a signed receipt.
  • Synthetic, public or test data only: real confidential data belongs on your own hardware.
The open stack

A notice of error, the account data and the investigation in; every Reg E clock with its rule, the file's gaps, and a signed record. The investigator decides.

For bank, credit union and fintech disputes teams, and the compliance officers who answer for the files. Give it the consumer's notice of an electronic fund transfer error (a chat, call transcript, form or letter), the account's transactions as CSV and the investigation: notes, events, the investigator's determination and the results letter. Code computes every Regulation E clock from the dates, with the rule cited: the notice within 60 days of the statement, 10 or 20 business days to decide, provisional credit and its notice, 45 or 90 days with the credit, the report within 3 business days and the correction within 1 (12 CFR 1005.11; 1005.18(e) for prepaid; 1005.33 for remittances). Qwen3.8-27B reads the notice's required elements, the notes and the letter, and every quote it gives is found word for word. For a no-error or different-error finding, the file cannot be closed until the letter explains the findings for this case, notes the right to request the documents relied on, and the documents are listed. It never decides a claim: the determination is the investigator's, recorded exactly as entered in a signed, hash-chained record.

Deployment
Self-host first
Regulatory
Consumer notices and account data are nonpublic personal information (Gramm-Leach-Bliley): run it on the institution's own hardware; the hosted demo takes synthetic disputes only. Rules read on 26 Sep 2026 from eCFR (the version of 1 Sep 2026; 12 CFR 1005.11 last amended 13 Feb 2018): notice within 60 days after the statement first showing the error is sent (1005.11(b)(1)(i)); determine within 10 business days (1005.11(c)(1)) or, with provisional credit within 10 business days and notice of it within 2, within 45 days (1005.11(c)(2)); 20 business days for a transfer within 30 days after the first deposit (1005.11(c)(3)(i)) and 90 days for a POS debit card transaction (including mail, phone and online orders, not ATMs; comment 11(c)(3)-1), a transfer not initiated in a state, or a new account (1005.11(c)(3)(ii)); report within 3 business days and correct within 1 (1005.11(c)(1), (c)(2)(iii)-(iv)); for no error or a different error, a written explanation and the right to request the documents relied on (1005.11(d)(1)); prepaid accounts without statements, 120 days from posting (1005.18(e)(2)(ii)); remittances, 180 days' notice and 90 days to decide, with an explanation that addresses the sender's complaint (1005.33(b), (c), (d)); records kept 2 years (1005.13(b)). A transfer the consumer was tricked into sending is initiated by the consumer, which the definition of an unauthorized transfer (1005.2(m)) does not cover; transfers made with access information obtained from the consumer by fraud are unauthorized (comment 2(m)-3; CFPB EFT FAQs, updated 13 Dec 2021 and online on 26 Sep 2026). The CFPB's December 2024 suit over Zelle fraud was dismissed with prejudice on 5 Mar 2025. The tool shows these as questions with the rule text; the investigator decides. Business days default to the Federal Reserve Banks' holidays (Board schedule K.8); Reg E counts the institution's own (1005.2(d)). Not covered: Regulation Z credit-card disputes, card-network rules, state law. Not legal advice.
Architecture
Text description

A consumer's notice of error, the account's transactions as CSV, and the investigation notes, events, determination and results letter go into decosa-api. Code computes every Regulation E clock from the dates with the CFR rule cited. Qwen3.8-27B reads the notice's required elements, the notes and the letter; code keeps an answer only when its quote is found word for word, and the grounding judge checks each fact in the letter against the file. A rule turns this into a checklist and a file status: open, gaps or complete. The investigator's determination is copied as entered and never set by the tool. Outputs: clocks and a timeline, the gaps, coverage questions with the rule text, and a signed hash-chained record. Hosted calls get gateway-signed receipts; a self-hosted box signs with its own key.

Architecture

At a glance

What it gives you
Every Reg E clock with its rule, start, due date and arithmetic; a timeline; the notice's required elements with quotes; a checklist of the file's gaps; a check of the results letter; coverage questions with the rule text; a Markdown file and a signed record.
What it does not do
It never decides a claim, denies one or drafts a denial letter: a named investigator does, and the file keeps their determination as entered. It does not cover Regulation Z credit-card disputes, card-network chargeback rules or state law, and it does not read your core system: send it the CSV.
Data retention
Nothing kept on the server. Notices, account data and files live in memory for the request; logs carry counts only. You keep the signed record with the dispute, at least two years (12 CFR 1005.13(b)).
What leaves the box (hosted demo)
The notice, notes, letter and the disputed transfers go to Qwen3.8-27B through the Decosa API, whose receipts hold hashes, not text. Self-hosted, nothing leaves. The hosted demo is for synthetic disputes only.
Model calls per file
One for the notice, one for the notes, one for the letter and one grounding call per letter sentence: 1 to 14 calls on the demo files. The clocks are code.
Typical run cost
About a cent or less at the gateway list price for the card-not-present file; a little more for the P2P scam file with a longer letter. Each run shows its own measured cost.
Business days
Weekdays minus the Federal Reserve Banks' holidays (a Saturday holiday is not moved). Reg E counts your own business days, so list any other day you are closed.
Quality tiers

Pick the tier for the quality you need

Same app at every tier. What changes is the models, the hardware they need, and whether receipts are signed. Scores are measured with the source named, or marked not measured.

  • Lite

    one 48 GB card

    The same pipeline on a smaller mixture-of-experts model. The clocks are code and identical; the reading accuracy on this task is unknown.

    Models
    • Gemma 4 26B A4B (instruction-tuned)
    Hardware
    1x L40S or RTX 6000 Ada 48 GB (not measured)
    Quality evidence
    • notice elements and letter checksnot measured yet
    Latency
    not measured yet
    Verification
    Proof: partialSelf-host onlyDirect route: calls are attested by the box's key; no gateway receipts.
  • In the hosted demo

    Standard

    the hosted demo, one 96 GB card

    Qwen3.8-27B reads the notice, the notes and the letter; the clocks, the quote checks, the checklist and the file status are plain code. Every model call receipted.

    Models
    • Qwen3.8-27B (NVIDIA NVFP4)
    Hardware
    1x RTX PRO 6000 Blackwell 96 GB
    Quality evidence
    • clocks: due dates and statuses against a second implementation (600 random disputes, 2026 to 2030, 2,763 clocks)2,763/2,763; the oracle was written by the same author, so this checks the code, not the reading of the ruledecosa-api docs/evals/reg-e-dispute-file.md, 2026-09-26
    • notice elements, test split (40 synthetic notices, run once): 'absent' flagsprecision 0.977 (43/44), recall 0.956 (43/45); all five elements right on 37/40decosa-api docs/evals/reg-e-dispute-file.md, measured on our server 2026-09-26, gateway route; prompts frozen on a 16-notice dev set
    • denial-letter completeness, test split (20 templated letters)explanation 20/20, right to documents 20/20, debit notice 20/20; small templated setdecosa-api docs/evals/reg-e-dispute-file.md, measured on our server 2026-09-26
    • automated decisions (5 samples and 4 injection attempts on the real model, plus unit tests)0 of 9decosa-api docs/evals/reg-e-dispute-file.md, 2026-09-26
    • real, redacted bank notices and lettersnot measured yet
    Latency
    measured on our server under a shared gateway: seconds to over a minute per file with a letter (about half a minute typical); about a dozen model calls per file with a letter
    Verification
    Proof: strongHosted: gateway-signed receipt per model call. Self-hosted: attested by the box's key.
  • Best

    DeepSeek-V4-Flash on two more cards

    A larger model for long call transcripts and dense case notes.

    Models
    • DeepSeek-V4-Flash (NVIDIA NVFP4)
    Hardware
    2x RTX PRO 6000 96 GB
    Quality evidence
    • notice elements and letter checksnot measured yet
    Latency
    not measured yet
    Verification
    Proof: partialSelf-host onlyNot a hosted model: calls are attested by the box's key only.
  • Needs more compute

    Wanted: the best setup

    two large judges from different families

    DeepSeek-V4-Flash and GLM-5.3-Flash each read the file, and a finding stands when they agree; disagreements go to the reviewer. Dispute files stay on your own hardware, never on community providers. Not served yet.

    Models
    • DeepSeek-V4-Flash (NVIDIA NVFP4)
    • GLM-5.3-Flash
    Hardware
    Your own hardware: 2x 96 GB cards for DeepSeek-V4-Flash plus 2x 96 GB for GLM-5.3-Flash, or one Mac Studio with 512 GB holding both 4-bit builds (156 + 165 GB, sizes from our Mac; not run together yet). Estimate.
    Quality evidence
    • notice elements and letter checksnot measured yet
    Latency
    not measured yet
    Verification
    No proof yetSelf-host onlyOn your own hardware its calls are attested by the box's key only: not a hosted model there, so no gateway receipts. Never sent to community providers.
    Not served yet. It needs more than one 96 GB card, so it runs on your own bigger box.
Components

Every model in the stack

Models in this stack. Each row has a button that shows its licence, engine, verification and evidence.
ModelDetails
Reads the consumer's notice (the required elements, the error asserted, who made the transfer, the transfers named), the investigator's notes (evidence reviewed, waiting for paperwork, carelessness cited) and the results letter (explanation specific or generic, right to documents, debit notice), and judges each letter sentence against the file (the grounding judge)Qwen3.8-27B (NVIDIA NVFP4)nvidia/Qwen3.8-27B-NVFP4 on Hugging Face (opens in a new tab)
27.8B · 57 GBProof: strongIn the hosted demo
Lite tier: the same pipeline on a 48 GB cardGemma 4 26B A4B (instruction-tuned)google/gemma-4-26B-A4B-it on Hugging Face (opens in a new tab)
25.2B (3.8B active)No proof yetSelf-host only
Best tier: a larger model for long call transcripts and dense case notesDeepSeek-V4-Flash (NVIDIA NVFP4)nvidia/DeepSeek-V4-Flash-NVFP4 on Hugging Face (opens in a new tab)
284B (13B active) · 192 GBNo proof yetSelf-host only
Second judge, from another familyGLM-5.3-Flashzai-org/GLM-5.3-Flash on Hugging Face (opens in a new tab)
321B (18B active) · about 170 GB (estimate)No proof yetSelf-host only

Measured

Are the clocks right, and does it catch the letter examiners cite?

The clocks were checked against a second implementation on 600 random disputes. The notice and letter checks ran on synthetic notices and letters with planted gaps: prompts were written on a dev split, then a test split was run once.

Clocks agreeing with the oracle
2,763 of 2,763600 disputes, 2026 to 2030, Federal Reserve holidays
Missing notice elements flagged
43 of 45test split; 1 false flag in 44
Generic 'no error' letters and missing right-to-documents sentences caught
20 of 20 letters right on all three itemstest split, templated
Automated decisions
0 of 9real model, including 4 injection attempts

Where it fails

On notices, a detail that only hints at an account ("my prepaid card" in the provider's own chat) was read as identifying it, and a transfer confirmation number was not. Who made the transfer is a hint only: raw agreement 24 of 40, several of our labels were wrong, and it only picks which coverage note the investigator sees.

What it does not show

Every notice and letter is synthetic and templated, written by the same author as the prompts. The CFPB complaint database's narratives were the planned real-world input, but its public API no longer returns them. Run your own notices and letter templates through the rehearsal bundle before relying on it.

Source: decosa-api docs/evals/reg-e-dispute-file.md, 26 Sep 2026

Around the models

Tools, services and hardware

Tools

Services

  • decosa-api:8445
    ${DECOSA_REGISTRY}/decosa-api:0.1.0

    Intake, the clocks, the quote checks, the checklist, grounding, signing and the HTTP API (/rege/*). No GPU. Binds 127.0.0.1 by default.

  • decosa-llm:8000
    ${DECOSA_REGISTRY}/decosa-llm:0.1.0

    vLLM OpenAI endpoint for Qwen3.8-27B. Internal to the compose network.

Hardware

  • 1x RTX PRO 6000 Blackwell 96 GB Fits

    Measured: the hosted demo's Qwen3.8-27B runs on one of these cards on our server.

  • 1x L40S / RTX 6000 Ada 48 GB

    Not measured. FP8 Qwen3.8-27B with a shorter context, or Gemma 4 26B A4B (lite).

  • CPU only Fits

    The clocks (POST /rege/clocks), the signed record and verification need no GPU; reading the notice, notes and letter needs the model.

Latency per lane

  • one file with notes and a letter, busy shared gateway37.8 s

    Measuredmeasured on our server 2026-09-26, 10 runs of the four demo files with a letter, gateway route: 7.6 s to 96.8 s depending on gateway load

  • one file with notes, no letter (open file)6.4 s

    Measuredmeasured on our server 2026-09-26, smoke run of p2p-takeover-open (2 model calls), gateway route

  • clocks only50 ms

    Estimateestimate: no model call

Assemble it

Run this exact stack on your machine

Paste into Claude Code / Codex to assemble this stack locally. The prompt checks your GPU, pulls the pinned models, writes the compose file and runs a smoke test.

reg-e-dispute-file/assemble-prompt.md201 lines
# Assemble the Decosa Reg E dispute investigation file on this machine

You are setting up a self-hosted Regulation E dispute file on this Linux machine for a bank, credit union or fintech
disputes team. It reads a consumer's notice of an electronic fund transfer error (a chat, call transcript, form or
letter), the account's transactions as CSV, and the investigation notes, events and results letter, and returns:
- every Reg E clock computed in code with the rule cited (12 CFR 1005.11, 1005.18(e) for prepaid, 1005.33 for
  remittances): notice timeliness, 10 or 20 business days, provisional credit and its notice, 45 or 90 days, the report
  within 3 business days and the correction within 1, plus a timeline;
- the notice's required elements, each quoted word for word;
- a checklist of the file's gaps, including a check that a no-error letter explains the findings for this case and
  notes the consumer's right to request the documents relied on;
- a signed, hash-chained investigation record.

Work step by step, show me each command before running anything that needs sudo, and stop if a check fails.

**Before anything else, remind me:**
- Consumer notices and account data are nonpublic personal information. Keep everything on this machine: the model
  route stays local (`direct`), and nothing goes to a hosted service.
- It never decides a claim. A named investigator enters the determination; the tool records it as entered. It is not
  legal advice, and it does not cover card-network rules, Regulation Z or state law.

Repeat both points in your final summary.

## Step 0: set up with a coding agent, rehearse on mock data, then go private

This prompt is for a coding agent running on the machine that will host the service. We recommend Claude Code with
Claude Opus 5.5; any capable coding agent works. Work in this order:

1. Set up on mock data only. During the whole setup you (the agent) work with the synthetic sample bundle below and
   nothing else. Do not ask me for real data, and do not open, read, list or copy files that hold real data, even to
   "test with something realistic".
2. Rehearse. When the steps below are done and the service is healthy, fetch the mock-data bundle for this tool,
   https://decosa.ai/samples/reg-e-dispute-file.zip (6 KB, 14 checks, synthetic or openly licensed: see `licence` in expected.json),
   show me what is in it, and run the rehearsal against the local API:
   `docker compose exec api python scripts/rehearse.py reg-e-dispute-file` (the api image carries the same bundle under /app/rehearsal/reg-e-dispute-file/;
   with no key set, the script asks the local API for a short demo token). From a decosa-api checkout instead:
   `python scripts/rehearse.py reg-e-dispute-file --bundle reg-e-dispute-file.zip --base-url http://127.0.0.1:<PORT>`.
   It sends the mock inputs to the local API and prints PASS or FAIL for each expected property (for example: "the provisional credit notice is due two business days after the credit (4 Sep 2026) and came late (no model)", "the May charge was reported more than 60 days after its statement", "a debit card online purchase gets the 90-day period"). Show me
   the full output. Every check must pass. If one fails, fix the install and run it again; never edit `expected.json`
   to make a check pass.
3. Stop there. Once the rehearsal passes, tell me, and I will run my own data against the local API myself, on this
   machine.

For the person running this: a coding agent that runs in the cloud sees everything in its context, including files it
reads, command output and anything pasted into the chat. Keep real data out of the chat and out of anything the agent
can read. Switch to your own data only after the rehearsal has passed and the agent's work is done.

## What you are building

| service | image | model | port |
|---|---|---|---|
| `llm` | `${DECOSA_REGISTRY}/decosa-llm:0.1.0` (vLLM 0.29.0, `vllm/vllm-openai@sha256:c2914767605584b6d8f45686b82de173ecc99e781897aa3d0a66dacd72c51ae1`) | `nvidia/Qwen3.8-27B-NVFP4` @ `482ca0f3832238542f8f5295dde86b5f22711d80`, Apache-2.0 | internal 8000 |
| `api` | `${DECOSA_REGISTRY}/decosa-api:0.1.0` (no GPU) | none | `127.0.0.1:8445` |

## 1. Check the GPU, driver and Docker

1. Run `nvidia-smi`. I need one NVIDIA GPU with at least 48 GB and driver 580 or newer.
   - Blackwell (RTX PRO 6000, B200): use the defaults below (NVFP4). This is the measured setup.
   - Hopper (H100/H200) or 48 GB Ada/L40S: set `LLM_MODEL=Qwen/Qwen3.8-27B-FP8` and `LLM_REVISION=main`. On a 48 GB card, also
     set `LLM_MAX_LEN=32768`. Not measured.
   - Under 48 GB: stop and tell me it will not fit.
2. Check `docker --version`, `docker compose version` and `docker run --rm --gpus all ubuntu nvidia-smi`. If Docker or the
   NVIDIA Container Toolkit is missing, install them from the official Docker and NVIDIA repositories. Then run
   `sudo nvidia-ctk runtime configure --runtime=docker` and restart Docker.
3. Confirm about 60 GB of free disk.

## 2. Get the images

The images are **on request** while self-host is in early access: ask at https://decosa.ai/contact?topic=self-host, and Decosa sends the registry (set it as `DECOSA_REGISTRY`), pull access and the compose file. Try `docker pull ${DECOSA_REGISTRY}/decosa-{llm,api}:0.1.0`.

If a pull fails, build from source once the `decosa-api` source is published:
- clone it;
- in the clone, run `docker build -f docker/api/Dockerfile -t ${DECOSA_REGISTRY}/decosa-api:0.1.0 .`;
- run `docker compose build llm` from its compose file.

If neither works, stop and tell me.

## 3. Write the compose file

Create `~/decosa-rege/.env`:

```bash
DECOSA_TAG=0.1.0
DECOSA_GPU=0
LLM_MODEL=nvidia/Qwen3.8-27B-NVFP4
LLM_REVISION=482ca0f3832238542f8f5295dde86b5f22711d80
LLM_MAX_LEN=65536
LLM_GPU_UTIL=0.85
DECOSA_SIGNER_NAME="<who signs these files, e.g. Example Bank disputes operations>"
```

Create `~/decosa-rege/docker-compose.yml` with exactly these services:

```yaml
name: decosa-rege
x-health: &health
  interval: 15s
  timeout: 5s
  retries: 5
services:
  llm:
    image: ${DECOSA_REGISTRY}/decosa-llm:${DECOSA_TAG}
    deploy: { resources: { reservations: { devices: [ { driver: nvidia, device_ids: ["${DECOSA_GPU:-0}"], capabilities: [gpu] } ] } } }
    ipc: host
    restart: unless-stopped
    volumes: [hf-cache:/root/.cache/huggingface]
    command: ["${LLM_MODEL}", "--revision", "${LLM_REVISION}", "--served-model-name", "qwen3.8-27b",
              "--language-model-only", "--max-model-len", "${LLM_MAX_LEN}", "--gpu-memory-utilization", "${LLM_GPU_UTIL}",
              "--max-num-seqs", "16", "--kv-cache-dtype", "fp8_e4m3", "--speculative-config", '{"method":"mtp","num_speculative_tokens":3}',
              "--seed", "0", "--enable-force-include-usage", "--disable-uvicorn-access-log", "--host", "0.0.0.0", "--port", "8000"]
    healthcheck: { <<: *health, test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=4)"], start_period: 900s }
  api:
    image: ${DECOSA_REGISTRY}/decosa-api:${DECOSA_TAG}
    restart: unless-stopped
    depends_on: { llm: { condition: service_healthy } }
    environment:
      DECOSA_LLM_ROUTE: direct                  # local model only; receipts are signed by this box's key ("attested")
      DECOSA_LLM_URL: http://llm:8000/v1
      DECOSA_LLM_MODEL: qwen3.8-27b
      DECOSA_LOCAL_SIGNING: "on"                # Ed25519 key created at /data/attest/ed25519.pem on first start
      DECOSA_SIGNER_NAME: ${DECOSA_SIGNER_NAME}
      DECOSA_SESSIONS_PER_IP_HOUR: "1000"
      DECOSA_BUDGET_LLM_TOKENS: "200000"        # per session; one file needs up to about 5,500 generated tokens
      DECOSA_SESSION_TTL_S: "28800"
      DECOSA_REGE_MAX_CONCURRENT: "3"
      DECOSA_CORS_ORIGIN_REGEX: '^https?://(localhost|127\.0\.0\.1)(:\d+)?$$'
    ports: ["127.0.0.1:8445:8445"]
    volumes: [decosa-data:/data]
    healthcheck: { <<: *health, test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8445/healthz', timeout=4)"], start_period: 20s }
volumes: { hf-cache: {}, decosa-data: {} }
```

Use the named volume `decosa-data` exactly as written. A host bind mount owned by root makes the API fail on
`/data/keys.sqlite`.

Run `docker compose up -d`, then poll `docker compose ps` until both services are healthy. The LLM takes 5-10 minutes
the first time. `curl -s localhost:8445/healthz` should show `"llm": true` (`asr` is false here, which is fine).

## 4. Smoke test

The clocks need no model:

```bash
API=localhost:8445
curl -s $API/rege/clocks -H 'content-type: application/json' -d '{"sample_id":"cnp-generic-denial"}' \
  | jq -c '[.rows[] | {id, due, status}]'
```

Pass if `provisional_credit_notice` is `missed` (due `2026-09-04`), `notice:T-0512` is `late_notice` (due `2026-08-01`)
and `determination` is due `2026-11-18` (90 days: a debit card online purchase).

Then the files (synthetic disputes):

```bash
TOKEN=$(curl -s $API/demo/session -H 'content-type: application/json' -d '{"vertical":"reg-e-dispute-file"}' | jq -r .token)
for s in cnp-generic-denial p2p-scam-consumer-sent p2p-takeover-open; do
  curl -s $API/rege/file -H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
    -d "{\"sample_id\":\"$s\"}" > /tmp/rege-$s.json
  jq -c '{status: .file_status.status, cannot_close: (.file_status.cannot_close != null), outcome: .determination.outcome,
          gaps: .file_status.gaps, receipts: (.receipts|length), statuses: ([.receipts[].status]|unique)}' /tmp/rege-$s.json
done
jq '{record}' /tmp/rege-cnp-generic-denial.json | curl -s $API/record/verify -H 'content-type: application/json' -d @- | jq '{ok, summary}'
```

Pass if:
- `cnp-generic-denial` is `gaps` with `cannot_close` true, the outcome `no_error` exactly as entered, and gaps including
  `explanation`, `right_to_documents` and `documents_relied_on`;
- `p2p-scam-consumer-sent` is `gaps` (the determination came late with no provisional credit, and the claim was held
  for an affidavit) and `.coverage[0].id` is `consumer_sent`;
- `p2p-takeover-open` is `open` with outcome `null`: no determination was entered, so none exists;
- every receipt has `"status": "attested"`, and the record verifies (`ok: true`).

You can also run the rehearsal bundle from the decosa-api source: `python scripts/rehearse.py reg-e-dispute-file
--base-url http://localhost:8445` (14 checks).

## 5. Point your case system at the local API

- Base URL: `http://localhost:8445`. For a web app, set `NEXT_PUBLIC_DECOSA_API=http://localhost:8445`. Add other origins to
  `DECOSA_CORS_ORIGINS`.
- `POST /rege/file` takes `{regime?: account|prepaid|remittance, notice: {text, received, channel?, written_confirmation?},
  account?: {first_deposit?, reg_t?}, transactions_csv, disputed_ids?, investigation: {investigator?, notes?, events?,
  documents_relied_on?, letter?, determination?: {outcome, by, date}}, closed_days?, today?}`. It returns JSON, or streams
  Server-Sent Events when asked with `Accept: text/event-stream`. `POST /rege/clocks` takes the same dates without text
  and calls no model.
- The CSV needs `id,date,amount,type,description`; add `statement_sent` (or `pending`) so the 60 days can be counted.
  Negative amounts are debits.
- Business days default to weekdays minus the Federal Reserve Banks' holidays. Reg E counts the institution's own
  business days (12 CFR 1005.2(d)): list any other day you are closed in `closed_days`.
- `GET /rege/info` lists each rule with its citation, link and the exact words relied on.
- The server stores nothing. Keep each signed record (JSON) with the dispute for at least two years
  (12 CFR 1005.13(b)(1)). Anyone can re-check it with `POST /record/verify` against the key at `GET /attest/signing-key`.
- Keep the API on 127.0.0.1. For other users on the LAN, put a TLS reverse proxy with authentication in front and set
  `DECOSA_TRUSTED_PROXIES`.

## 6. Keep the direct route

`DECOSA_LLM_ROUTE=gateway` would send prompts to the hosted Decosa
API, and those prompts contain the consumer's notice and
account data. Never use it for real disputes. At most, use it for synthetic training material.

Finish with a summary: what is running, the health output, the smoke-test results, and the reminders above.
Rules and regulations it checks againstDated, linked to the primary source; not legal advice

Regulation watch

Loading the watch status…

13 laws, rules and guidance pages cited; 10 watched nightly at the primary source. A change marks this page for a human re-check; nothing is edited automatically. What we cite and how it is watched

Technical detailsModels, where it runs, labels

In short

Last reviewed

What it is
A Reg E dispute investigation file for disputes teams: every error-resolution clock computed from the dates with its CFR rule, the notice's required elements quoted, the file's gaps listed, and the no-error letter checked. The investigator decides every claim.
Who it's for
Disputes operations teams and compliance officers at banks, credit unions, fintechs and remittance providers.
Where it runs
Self-host for real accounts (hosted demo: synthetic disputes only)
Key numbers

On a held-out set of 40 synthetic notices it flagged 43 of 45 missing elements with one false flag, and caught every generic letter in 20 templated tests; all synthetic, written by the same author.

  • 0.956 (43/45) Missing notice elements flagged (recall) (test split, n = 45)
  • 0.977 (43/44) Missing-element flags that were right (precision) (test split, n = 44)
  • 37 / 40 Notices with all five elements right (test split, n = 40)
  • 37.8 s Median end-to-end run, hosted (QA sweep 2026-09-26)
All results, datasets and caveats
Models
Qwen3.8-27B
Where
Self-host for real accounts (hosted demo: synthetic disputes only)
Checks
Receipt per model call; every clock computed in code with its CFR rule; every quote found word for word; signed hash-chained investigation record
Output
Signed record or verdict · Structured data
Data
Personal data · Confidential business data
Hardware
1× 96 GB GPU
Licence
Permissive (Apache-2.0, MIT)
Runs in
Self-host

Questions people ask

Does it decide or deny Reg E claims?

No. A named investigator enters the determination and the file records it exactly as entered; no model output or rule can set it. The tool drafts no denial letter. It checks the investigator's letter and lists the facts on file an explanation can use.

Which Reg E deadlines does it compute?

The notice within 60 days of the statement, 10 business days to decide (20 for a new account), provisional credit within that period and notice of it within 2 business days, 45 days (90 for POS debit card, foreign or new-account transfers), the report within 3 business days and the correction within 1, from 12 CFR 1005.11, plus the prepaid and remittance rules.

What does a Reg E dispute investigation file need for a no-error finding?

A written explanation of the findings and a note of the consumer's right to request the documents relied on (12 CFR 1005.11(d)(1)). The file cannot be marked complete without a specific explanation, that sentence and a list of the documents. Examiners have cited generic 'no error' letters from dispute-system templates.

Does Reg E cover a P2P payment the consumer was tricked into sending?

The tool shows it as a question with the rule text rather than answering it. The definition of an unauthorized transfer covers transfers initiated by someone other than the consumer (1005.2(m)); transfers made with access information obtained from the consumer by fraud are unauthorized under the commentary and the CFPB's FAQ. The investigator decides, and the clocks run either way.

How are business days counted?

Weekdays minus the Federal Reserve Banks' holidays, where a Saturday holiday is not moved. Reg E counts the institution's own business days, so you can list any other day you are closed.

Where does account data go?

Self-hosted, nothing leaves your hardware. The hosted demo takes synthetic disputes only; there, the text goes to Qwen3.8-27B through our gateway, whose receipts hold hashes, not text. Nothing is kept on the server.

Ask a question or leave feedbackWe read every message and publish useful answers
Questions & feedback

Ask about Reg E dispute investigation file

We read every message. Questions, comments and our answers show here once we have reviewed and approved them.

Loading questions…

This is a

Plain text. Please leave out personal, patient or client data.

Shown with your message if we publish it. Leave blank to post as “A visitor”.

Nothing appears here until we have read and approved it.