Skip to content

Latest commit

 

History

History
108 lines (81 loc) · 3.15 KB

File metadata and controls

108 lines (81 loc) · 3.15 KB

Architecture

My Reps has one shared behavior layer and three thin adapters.

  • Core: validation, runtime mode selection, source facades, canonical representative mapping, envelopes, schema, and source status.
  • CLI: terminal adapter for agents, local demos, and contract checks.
  • API: HTTP adapter for the web app and Cloudflare Pages Function.
  • Web: React UI that renders the canonical envelope returned by the API.

The important design choice is that the API does not shell out to the CLI. Both the API and CLI import the same TypeScript core.

Dependency Direction

flowchart TD
  cli[CLI] --> core[Shared core]
  api[HTTP API] --> core
  worker[Cloudflare Pages Function] --> api
  web[React web UI] --> apiEndpoint[/POST /api/lookup/]
  apiEndpoint --> worker

  core --> validation[Validation]
  core --> envelope[Schema-versioned envelope]
  core --> mode[Runtime mode selector]
  core --> sources[Representative sources]

  sources --> mock[Mock fixture source]
  sources --> live[OpenStates + Census live source]
Loading

Request Flow

CLI lookup:

georep lookup --address "530 S King St, Honolulu, HI 96813" --mock
  -> shared validation
  -> runtime mode selection
  -> representative source
  -> canonical envelope
  -> stdout JSON

Web lookup:

Browser form
  -> POST /api/lookup
  -> shared validation
  -> runtime mode selection
  -> representative source
  -> canonical envelope
  -> React renders cards/status

Runtime Modes

  • mock: deterministic, fixture-backed, no live upstream calls.
  • live: uses server-side live source configuration.
  • auto: defaults to mock unless live behavior is explicitly configured.

Mock mode is the reliable public demo path. Its representative records are synthetic and intentionally fake.

Live mode currently uses Census Geocoder for address-to-point lookup and OpenStates/Plural Open for state legislative representatives. It reports partial coverage because county and local offices are not covered by that live path.

Envelope Contract

All commands and API lookup responses use a schema-versioned envelope:

{
  "schema_version": "1.0",
  "success": true,
  "data": {
    "representatives": []
  },
  "meta": {
    "source": "mock",
    "sources": ["mock"],
    "is_mock": true,
    "query": {
      "type": "address"
    },
    "count": 0,
    "latency_ms": 0,
    "generated_at": "2026-05-23T00:00:00.000Z"
  }
}

The envelope lets the CLI, API, and UI share one contract. It also gives agents a stable shape to inspect with georep schema.

Privacy Boundary

Validation strips behavior down to a safe query shape before the source layer is called. Failure envelopes do not echo raw addresses or exact coordinates.

The code should not store:

  • exact addresses
  • exact coordinates
  • raw upstream bodies
  • source credentials

Source credentials are read from environment variables or Cloudflare project secrets and stay server-side.

Why Not API To CLI?

Running the CLI from the deployed API would add an unnecessary process boundary and would not fit Cloudflare Pages Functions well. Keeping both surfaces as adapters over shared core code makes behavior easier to test and keeps deploys simple.