Index

Pages, systems, publications, and public work.

Pages

Research & publications

Projects

Fieldwork & access

Elsewhere

Case Law Explorer platform

A modular legal-research platform that joins court-data search, shared identity, scoped access, rate limits, APIs, and reproducible deployment.01

A guarded query across the legal-data estate.

The current system joins three corpus-specific ingestion paths to one schema and API. Identity, entitlement, product delivery, and operations remain separate boundaries.

Scroll through seven system boundaries.

  1. 01Source materialRS · ECHR · CJEURechtspraak XML · HUDOC · CELLAR
  2. 02ETL + migratesource id → ECLIAirflow workers · provenance · checksums
  3. 03Unified data planecle_v2cases · corpus satellites · text · citations
  4. 04API contract15 JSON routessearch · text · expand · links · methods
  5. 05Optional policy checkPOST /v1/checkidentity ≠ scope · cost · quota · audit
  6. 06Product boundarySvelteKit /api/* proxyserver credential · on-demand full text
  7. 07Operations planeCoolify composemigrate · backup · SQL · ETL
Canonical relationscases → rs_document | echr_document | cjeu_documentShared case_text and integer-keyed case_citation relations connect all three corpora.
Bounded graph responsenextCursor · limits · statisticsSafe · partialReasonsCompleteness and graph-safety state travel with every paged result.
Two request posturesREQUIRE_AUTH=false | trueOff means no access-service call. On means one entitlement decision per guarded request.
Subject operations/internal/users/{subject}Short-lived subject-bound tokens keep account export and erasure outside public CORS and quota rules.
Verified against the maintained citations-api, caselaw-access, caselaw-auth, and caselaw-coolify documentation. The retired /api/network route is deliberately absent; it now returns 410.

Google Spain, from public work to queryable graph.

Case C-131/12 enters through CELEX 62012CJ0131. Seven maintained contracts turn it into multilingual text, a stored citation relation, and a guarded result in the research workspace.

Google Spain SL and Google Inc. v AEPD and Mario Costeja GonzálezJudgment of the Court (Grand Chamber), 13 May 2014
ECLI
ECLI:EU:C:2014:317
CELEX
62012CJ0131
Procedure
Preliminary ruling
  1. CELEX
    62012CJ0131
    ECLI
    ECLI:EU:C:2014:317
    Case
    C-131/12
  2. Languages
    23 recovered
    English
    76,831 chars
    Source
    INFOCURIA_BLOB_HTML
  3. Metadata
    cases.parquet
    Text
    fulltexts.parquet
    Missing
    none reported
  4. From
    62012CJ0131
    Relation
    cites
    To
    62009CJ0509
  5. Identity
    cases.id
    Corpus
    cjeu_document.case_id
    Graph
    case_citation
  6. Route
    POST /api/cjeu
    Scope
    cjeu
    Depth
    1 out · 1 in
  7. Proxy
    /api/[...path]
    Result
    CJEU profile
    Reader
    /api/cjeu/text

Resolve the work

Boundary 01 · cellar-extractor · get_cellar()

The public CELLAR work binds the CELEX identifier to the court ECLI before any application row exists.

cdm:resource_legal_id_celex
  "62012CJ0131"
→ ECLI:EU:C:2014:317
Handoff

CELEX becomes the stable join key for metadata, renditions, and citation relations.

Recover renditions

Boundary 02 · cellar-extractor · get_case_data_by_celex_id()

Sector-6 retrieval prefers structured InfoCuria material, then fills missing language bodies from CELLAR items.

language  EN
format    html
source    INFOCURIA_BLOB_HTML
Handoff

Each rendition retains its language, format, and upstream provenance instead of becoming an anonymous text blob.

Normalize the record

Boundary 03 · cellar-extractor · fulltext_saving.py

Metadata and full text travel separately. The text sidecar carries CELEX, ECLI, provenance, format, language, and explicit missing reasons.

text_language   EN
text_format     html
missing_reasons ""
Handoff

The loader receives typed, inspectable fields; upstream absence remains data rather than disappearing as null.

Extract the edge

Boundary 04 · cellar-extractor · citations_adder.py

The work_cites_work predicate yields a directed edge from Google Spain to eDate Advertising, not a visual inference from the judgment text.

62012CJ0131
  └─ cites → 62009CJ0509
     ECLI:EU:C:2011:685
Handoff

Outbound and inbound relations are preserved separately because their upstream coverage differs.

Load the shared model

Boundary 05 · cjeu-migration · 50_load_cjeu.py

A shared case owns corpus-specific metadata, language-specific text, and integer-keyed citation relations without flattening their source semantics.

cases
├─ cjeu_document
├─ case_text × language
└─ case_citation × relation
Handoff

Natural identifiers resolve the case once; satellite and graph rows use the resulting internal key.

Serve a bounded graph

Boundary 06 · citations-api · api/cjeu

The CJEU handler searches the unified schema, walks CELLAR edges, and exposes whether the returned graph is complete enough for statistics.

degreesSource  1
degreesTarget  1
statisticsSafe true | false
Handoff

When enforcement is enabled, @protect("cjeu") resolves scope, cost, quota, and audit state before the handler runs.

Open it for research

Boundary 07 · citations · edgeApi.ts + citation-panel.svelte

The browser calls its own SvelteKit origin. The server adds the bearer credential, the result profile exposes CELEX-specific fields, and text loads by language on demand.

browser → SvelteKit proxy
        → guarded CJEU API
        → result + language reader
Handoff

The research surface receives a typed case and a qualified graph; neither the database nor service credential reaches the browser.

01 / 07 · Resolve the work
Concrete values were checked on 26 August 2026 against the maintained extractor and the public CELLAR endpoint. The cited relation is Google Spain → eDate Advertising. Verify the source judgment in EUR-Lex, the cited case in EUR-Lex, or inspect the public CELLAR package.

System boundary

Case Law Explorer is a legal-data platform, not only a search screen. Its deployed request path is browser → SvelteKit server proxy → citations-api → Postgres. Rechtspraak, HUDOC, and CELLAR enter through corpus-specific extraction paths before converging on the cle_v2 schema. Identity, entitlement, product delivery, and operations remain separate so that multiple research tools can share the corpus without sharing one application runtime.

Contribution

David’s work spans the Case Law Explorer search experience, shared interface packages, the account service, scoped API access, rate enforcement, modularization, Docker-based deployment, and server operations. It also includes work on the extraction and normalization path that supplies the research database.

Scope The platform builds on earlier Case Law Explorer work and is developed within a wider Maastricht research ecosystem. David's stated scope does not imply sole authorship of the datasets or research programme.

Consequential decisions

One case relation, three corpus satellites. cases is the shared ECLI-keyed entry point. rs_document, echr_document, and cjeu_document retain corpus-specific fields; case_text stores language-specific full text; and integer-keyed case_citation records the cross-corpus graph. This avoids flattening source-specific semantics into one oversized case table.

Search and full text have different costs. The API exposes fifteen JSON routes across Rechtspraak, ECHR, CJEU, combined search and expansion, statistics, communities, summaries, and legal-link resolution. Full text has a dedicated route per corpus, and the old generic /api/network route returns 410. The interface therefore loads large judgment bodies only when the reader asks for them.

Identity is not entitlement. Keycloak establishes who the caller is. caselaw-access separately decides whether that principal may use an endpoint, how much the route costs, which minute and daily limits apply, and why the request was allowed or denied. A valid identity therefore never silently becomes universal API access.

Completeness travels with the graph. Cursor state, result caps, partialReasons, and statisticsSafe remain part of the API response. A truncated network cannot accidentally reach a centrality method while presenting itself as complete.

Optional services remain optional in code. The core database, API, and frontend run without shared sign-in or rate enforcement. Auth and access connect over explicit URLs and credentials; enabling one does not import it into every product runtime. Public search, guarded APIs, and research workspaces can therefore adopt different access postures without forking the corpus.

Public and authenticated products share versioned interface primitives across Vue and Svelte. The deployment contract keeps each service replaceable and lets the search surface, research APIs, and internal workspaces evolve at different rates.

Account export and erasure use subject-bound, expiring service tokens on /internal/users/{subject} routes outside the public API prefix. Coolify composes the API, frontend, migrator, database, backup, signed SQL runner, and Airflow services; Airflow’s bookkeeping remains in a different Postgres instance from the case-law data.

Ingestion

CELLAR extraction is one component of this pipeline. European legal material is distributed across CELLAR, EUR-Lex, InfoCuria, RDF records, and multiple document manifestations. The extractor retrieves base metadata, follows the public CELLAR SPARQL citation graph, and adds full text, summaries, keywords, provenance, and explicit missing-data states.

Separate paths cover CJEU-style case law, national case-law material, legislation, and consolidated versions. Outputs support both tabular research and graph-ready node and edge projections. Missing values are retained with their causes because source absence, format drift, and incomplete enrichment affect the validity of downstream research.

Evidence

  • A live research interface at app.caselawexplorer.tech.
  • Published JavaScript and Python packages for interface, ingestion, authentication, and access layers.
  • Service-specific repositories for extraction, API, shared UI, authentication, access policy, and deployment.
  • Reproducible Docker configurations and documented operational boundaries.

Reflection

Good research infrastructure makes limits visible. Authentication remains optional where open access is appropriate; scopes and quotas are explicit where scarce resources need protection; and every service documents what it owns.

Design and implementation

Visual decision
The estate overview names the owned boundaries; the second trace follows one real CJEU judgment through CELLAR resolution, multilingual recovery, normalization, citation extraction, cle_v2, the guarded API, and the SvelteKit reader.
Access decision
Every boundary remains in an ordered text sequence. The active readout can be changed by pointer, previous/next controls, or arrow keys; reduced-motion visitors receive the same state changes without the route animation.
Delivery constraint
The concrete judgment values were checked through the maintained extractor and public CELLAR graph, then frozen into static HTML. This example sends no query, database identifier, service credential, or private deployment state.