Repository navigation
ADR 014 Sync Out
Accepted 2026-10-08. The product owner made the decision. Sync-out and the ENGAGE ingest are in the
eagle-demi repository; this page does not record which environment runs them.
ENGAGE (met-api) creates an engagement for a project and pushes it to eagle-api as a comment
period. The push goes to Eagle only. DEMI sees the period when eagle-api mirrors it
(Sync-Architecture). A failed ENGAGE push leaves no trace on either side: the engagement exists
in ENGAGE, the period does not exist in Eagle, and nothing reports the gap.
eagle-public's Angular line still reads comment periods from eagle-api, so Eagle has to hold them until that line retires. DEMI serves the React line and already holds a copy of every period.
Engagements flow ENGAGE → DEMI → Eagle. DEMI is the source of truth for them.
-
Ingest. ENGAGE calls
PUT /api/engage/engagements/{engagementId}. The route is specific to ENGAGE. There is no generic ingest route. See Connecting-an-Application-to-DEMI. - Outbox. Each stored row is queued on an Azure Storage queue. The worker re-reads the row when it runs, so a late or repeated message sends the current state.
-
Consumer registry.
src/sync-out/index.jslists consumers, each withname,enabled(),wants(row)andsend(row). Eagle is the first. Removing it means deletingsrc/sync-out/eagle.js, one line in the registry, thesyncOut.eaglesettings and their bicep app settings, and the Eagle half ofreconcile-engage.js. -
Eagle writes go through eagle-api's HTTP API. DEMI signs in as the Keycloak client
demi-sync-out. Nothing writes Eagle Mongo directly. -
Ownership by
sourceSystem. A row withsourceSystem: 'engage'belongs to ENGAGE. The Eagle mirror writes only the Eagle-owned fields onto it (ENGAGE-Rows-Reference). - Echo. eagle-api pushes every period it writes back to DEMI. The mirror keeps that push to the Eagle-owned fields and queues nothing, so the loop ends after one hop.
-
Reconcile.
reconcile-engage.jscompares ENGAGE rows with Eagle's copy and with ENGAGE's public list.--repairqueues drifted rows again, and DEMI's copy wins.
- A failed Eagle write is retried, then the worker moves it to a poison queue and logs the line the alert reads. A failed ENGAGE push gets an HTTP error that ENGAGE can log.
- A second system that needs these rows is one more consumer in the registry.
-
staffis a bypass role in eagle-api (JWT_BYPASS_ROLESinapi/helpers/auth.js). Thedemi-sync-outsecret is therefore broad write access to Eagle and lives only in Key Vault. - A staff edit in eagle-admin to an ENGAGE-owned period is overwritten by the next send or
--repair. - When the Angular line retires, the Eagle consumer is deleted and nothing else changes.
- The cutover and rollback order is in Sync-Architecture.
- A bridge from DEMI to Eagle outside DEMI. It needs its own copy of the row rules and its own credentials to DEMI, and failures sit in a third place.
- Cosmos change feed as the trigger. The feed also fires on ACL cascades and on the echo from Eagle, and it needs a lease container. Storage queues already have a poison queue and an alert.
-
A generic
/ingestroute. Each source has its own ownership rules and field names. A shared route needs a per-source switch inside it. -
Writing Eagle Mongo from DEMI. eagle-api stays the one writer of its database; its
controllers set
read,isPublishedand the milestone.
- Sync-Architecture — the sync-out section, cutover and rollback
- ENGAGE-Rows-Reference — field ownership, join rules, reconcile report
-
Identity-Model — the ENGAGE principal and the
demi-sync-outclient - ADR-007-Service-to-Service-Credentials — the credential model both use
- Environment Reality & Gotchas
- Architecture
- Seeding — filling Cosmos from Track and Eagle
- Sources and Status — every source, one state
- Search & Retrieval — overview
- Search Index Reference
- Search Query Construction
- Search Measurements
- Extraction Pipeline
- Extraction Quality — coverage, word-joining, tiling
- Identity Model — which id means what
- Attribute-Level Access — field-visibility levels, catalog
- Sync Architecture — how records get in
- Eagle Mirror Reference — mirrored kinds, refusals, drift classes
- ENGAGE Rows Reference — ENGAGE-owned comment periods, reconcile
- Public-Read Backfill — filling and repairing the mirror containers
-
Short Links —
/s/{code}redirect and/api/links -
Recent Uploads —
/api/documents/recent-uploads, eagle-public homepage panel - Reports — comment export and BCGW CSV reads
-
User Data — saved map areas, preferences,
/meroutes -
Bulk Download —
/api/bulk-downloads, zip jobs - Bulk Download: Operations — enable, poison-queue runbook
- Document Intake — upload link, malware scan, release
- Connecting an Application to DEMI
- Azure Environments
- Document Backup — archive copy of originals, run and check
- Document Backup: Revert and Drill — put documents back from the archive
- PDF Titles — public name written into stored PDFs, run, restore
- Secret Sync — Key Vault, secret-sync Function app, required names
-
Operating DEMI in Azure — deploy, verify
- Operating the DEMI Data Plane — devbox access, probes, audit and cost reads
- Edge ban detector — hourly timer, modes, kill switch, soak and promote
-
CI Workflows — every GitHub Actions workflow, trigger, identity, roles
- CI Deploy Workflows — eagle-demi staging and production deploys
- CI Admin Frontend Workflows — eagle-demi-admin checks and deploys
- Release Process — cutting, tagging, shipping and rolling back a version
- Runbook: Search Outage — index/app schema drift, diagnose, fix, roll back
- BC Gov Landing Zone
- Business Rules
- EPIC.search Business Rules — where DEMI differs from EPIC.search
- 001: Typesense for DFL Search — superseded
- 002: Async Processing (MongoDB Queue) — superseded
- 003: Rule-Based Classification
- 004: Read ACL Authorization Model
- 005: Cosmos Full-Text Search Ruled Out
- 006: AI Summarization over BM25
- 007: Service-to-Service Credentials
- 008: Audit and Usage Analytics Store
- 009: Track Feed — proposed
- 010: Attribute-Level Access Control
- 011: Public Read Surface
- 012: Public Config Surface
- 013: Stored Project Summaries — proposed
- 014: Sync-out to Eagle
- 015: Malware scanning on intake