Metadata-Version: 2.4
Name: oak-domain-legal-intake
Version: 0.1.0
Summary: Legal-intake (access-to-justice) domain plugin for the OakQuant timber substrate.
Author-email: Pumulo Sikaneta <pumulo@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: timber-common>=0.6.14
Provides-Extra: dev
Requires-Dist: fastapi>=0.110; extra == 'dev'
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# oak-domain-legal-intake

**An access-to-justice legal-intake domain for the OakQuant platform — the first
domain built on Timber's plugin system.**

[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/)

## What it is

`oak-domain-legal-intake` is a *discoverable* Timber domain plugin. Installing it adds a
legal-intake capability to an OakQuant deployment; leaving it out is a no-op. It is fully
**additive and opt-in** — it ships its own models, services, and integration points and
wires them into the platform's shared registries at startup, with **no edits to the core
Timber, Grove, or Acorn libraries**.

It is also the proving ground for OakQuant's domain-plugin pattern: the first domain built
on Timber's plugin system that is *not* the investments domain, demonstrating that a brand
new, unrelated domain can plug in cleanly through a single entry point per layer.

### Why legal intake — access to justice

Legal aid and pro-bono organizations triage far more people than they can serve. The
quality and consistency of that triage decides who gets help. This domain is the data
foundation for doing that triage **fairly, accountably, and observably** — built so the
people running it can see what happens and contest it. Several design choices encode that
intent directly into the schema:

- **Data minimization** — operational fields only; no free-text PII columns.
- **Protected attributes are isolated** in `IntakeCase.audit_attributes` (used only by a
  fairness audit), kept *out* of the operational fields used for routing.
- **Help, not gate** — a `Disposition` records a routing or referral, never a "denial".
- **Append-only logs** — the event and outcome logs support contestability and audit.
- **Meaningful human review** — `StaffDecision` captures the human's decision and any
  override, including the reason.

> **Phase 0 — instrumentation only.** This release captures the data foundation with
> **no live recommendation**: cases, an append-only event log, staff decisions (with
> override capture), dispositions, and delayed/partial outcomes. It records; it does not
> advise.

## The plugin shape

This package plugs into all three OakQuant layers through **one entry point per layer**.
Each layer discovers only its own entry-point group and imports only that entry point's
module — so the Timber layer never pulls in Grove/FastAPI or Acorn.

| Layer  | Entry-point group | Object                                                      | Contributes |
|--------|-------------------|-------------------------------------------------------------|-------------|
| Timber | `timber.domains`  | `oak_domain_legal_intake:LegalIntakeDomain`                 | ORM models + `intake` / `outcome` / `audit` services |
| Grove  | `grove.domains`   | `oak_domain_legal_intake.grove_plugin:LegalIntakeGroveDomain` | FastAPI router mounted under `/legal-intake` (`/health`, `/info`) |
| Acorn  | `acorn.domains`   | `oak_domain_legal_intake.acorn_plugin:LegalIntakeAcornDomain` | agent tool `legal_intake_status` (read-only) |

## What the domain provides (Phase 0)

### Models

All models subclass Timber's shared `Base` (`common.models.base.Base`), so defining them
adds them to `Base.metadata` and Timber's table-creation step creates their tables.

| Model          | Table                            | Role |
|----------------|----------------------------------|------|
| `IntakeCase`   | `legal_intake_cases`             | a matter in triage; operational fields only, protected attrs isolated in `audit_attributes` |
| `IntakeEvent`  | `legal_intake_events`            | append-only event log (intake / staff action / audit) |
| `StaffDecision`| `legal_intake_staff_decisions`   | human review with structured override capture |
| `Disposition`  | `legal_intake_dispositions`      | terminal routing/referral (help-not-gate: never a denial) |
| `OutcomeEvent` | `legal_intake_outcomes`          | ingested downstream outcomes, for later evaluation |

### Services

Registered under `service_registry.domain("legal_intake")`:

- **`intake`** (`IntakeService`) — `record_intake`, `record_event`, `list_queue`, `get_case`
- **`outcome`** (`OutcomeService`) — `ingest_outcome`, `list_outcomes`
- **`audit`** (`AuditService`) — `log`, `history`

## How discovery works

The domain advertises itself via the `timber.domains` entry point. At startup
(`initialize_timber`, **Step 8.5**), Timber discovers this package, instantiates
`LegalIntakeDomain`, and calls its `register(ctx)` **once, before table creation** — so the
registered models get their tables created in the following step. `register(ctx)` takes
every runtime dependency (db handle, registries) from the injected `DomainContext` rather
than importing core singletons, keeping the dependency direction one-way.

The Grove and Acorn plugins follow the same shape against their own entry-point groups and
contexts (`GroveDomainContext` / `AcornDomainContext`), registered when those apps start.

## Install

```bash
pip install oak-domain-legal-intake
```

This pulls in `timber-common>=0.6.14` (the plugin scaffolding: `ServiceRegistry`,
`DomainPlugin` / `DomainContext`, `timber.domains` discovery, and the init Step 8.5 hook).
Once installed, discovery is automatic via the entry points — no configuration needed. The
optional `dev` extra (`pip install "oak-domain-legal-intake[dev]"`) adds `pytest` and
`fastapi` for running the test suite, including the Grove plugin standalone.

## License

Apache-2.0. See [LICENSE](LICENSE).
