Skip to main content

Data-flow diagrams

Notation: rounded boxes are external entities, rectangles are processes, cylinders are stores. Arrows are data, not control. Numbers match the Level-1 processes.


Context (Level 0)

Complied does not e-file with HPD. assemble-filing-package ensures decided HPD documents exist, then writes a filing_packages row and join rows; a human files whatever documents they actually have. There is no merged-PDF download in the UI today.


Level 1 — the system

P3 is the Decide / Work / File / Money workspace, not a gated phase machine. projects.phase is an ops label written by setProjectPhase from the browser.


Level 2 — 1 Ingest

One edge function: sync-orchestrator. One domain loop: domain/src/ingestion/runFeed.ts. Eight feeds, sequential, idempotent on (agency, source_id).

Feeds that ship: HPD violations, HPD complaints, HPD litigation, DOB violations, ECB violations, OATH hearings, DOF liens, NYC 311.

Not wired in the orchestrator (REQUIREMENTS still wants them as intelligence): DOB permits, ACRIS, FDNY, DEP, DSNY-as-own-feed, evaluate-obligations. Building-facts / PLUTO is Layer 1 (fetchBuildingIdentities), run locally, not against prod. Events that cannot resolve a building_id must not land in public_events — quarantine is the defect surface, not a nullable FK.

Ops views: sync_health_summary, unlinked_events_by_reason. There is no staff "ingestion dashboard" page in the rebuilt UI. Known load bugs (HPD watermark poison, ECB 550k cap, DOB date): docs/compliance-ingestion-layers.md, ranked in docs/LIFECYCLE_ASSESSMENT.md §8 item 9.


Level 2 — 3 Project workspace

origin is immutable. Creating from a violation writes project_event_links at create time. After create, no UI calls linkProjectToEvent — so obligation / occupant-request projects open Decide with nothing to decide.

Phase is not on this pipeline. The header dropdown writes projects.phase; a trigger writes history. See GATING.md.


Level 2 — 4 Field + 5 Docs

XRF report generation is the only wired field-report path in the UI. generate-paint-chip-report, generate-dust-wipe-report, generate-abatement-report, and generate-coc exist as edge functions with no frontend invoker. There is no lab-result entry UI.

Storage layout: documents bucket {tenant_id}/{project_id}/{uuid}.pdf. Branding bucket {tenant_id}/logo.* and {tenant_id}/{client_id}/logo.*. Letterhead always comes from tenant_branding, never client_branding.

generate-proposal-pdf and generate-invoice-pdf skip unpriced services and return 200 — a $0 document is a silent failure, not an error.


Trust boundaries (worth a DFD of its own)

The browser never holds the service-role key. Edge functions that mutate documents or email accept either a user JWT that passes has_permission / is_platform_operator, or the service-role bearer (cron / operator invoke).

setProjectPhase is not an edge function — it is a client .update() under RLS. The advance_projects permission is UI-only.