1040 Fluxx Platform Interop---Requirements-&-Sizing-(v2 Workflow)
1040 Fluxx Platform Interop---Requirements-&-Sizing-(v2 Workflow)
Purpose: Translate the new event-driven 1040/Palantir workflow described in 1040_FLUXX_INTEROP_V2.md into a concrete, research-backed requirements list, gap analysis, and sized backlog (Epics → Stories, T-shirt sized Small/Medium/Large) across the fluxx-* microservices.
Method: Every finding below is based on direct inspection of the repos in this workspace (fluxx-classifier, fluxx-document-splitter, fluxx-extractor, fluxx-file-intake, fluxx-postal, fluxx-registration, fluxx-sql-server, fluxx-statuscheck) — READMEs, docs/, config.json / pubsub.config.json topic wiring, and the actual TypeScript source (handlers, orchestrators, repositories, migrations). Where the code disagrees with the informal description in the requirements doc, the code’s actual behavior is called out explicitly.
1. Naming Clarification (Assumption)
There is no repo literally named fluxx-fileupload. The upload endpoint described in requirement #1 (“Palantir calls the fluxx-fileupload endpoint with a PDF”) maps to the existing fluxx-file-intake service’s POST /v1/upload/:applicationId endpoint (uploadController.ts → uploadService.handleMultiFileUpload / handleChildFileUpload). This document proceeds on that assumption — flag if a distinct, new “fileupload” surface is actually intended.
Also note: fluxx-statuscheck is the only other fluxx-* repo not directly named in the requirements, but it consumes almost every topic in the platform for observability and will need updates to stay in sync with the new flow (see Epic 8).
2. Current State — What The Code Actually Does Today
The informal description at the top of 1040_FLUXX_INTEROP_V2.md (upload → extractor calls Databricks → polls job → Fluxx calls Palantir) undersells how much has already been built. The real current-state, confirmed in source, is:
Key architectural gaps this exposes (beyond the literal 7 bullet points)
- Two separate poll-and-lock engines exist (classifier’s
ClassificationPollingOrchestrator, extractor’sextractionJobPollingWorker) that both need to be replaced/augmented with event-driven completion — this is a bigger lift than “stop polling,” it’s swapping the completion trigger for two independently-built subsystems. - Extractor talks to Palantir directly, hard-coded to a single client (Palantir-specific
PalantirApiClient,ontologyActionUrl). Moving delivery tofluxx-postalmeans removing this direct dependency fromfluxx-extractorand generalizing delivery. to-sendhas no publisher today. Wiring the extractor’s completion event intoto-send(or a new topic postal also subscribes to) is the actual “last mile” connecting the new flow to the already-built postal delivery pipeline.deliveryMethod/content-shape (payload vs. SAS URL vs. blob URL) does not exist as a real, configurable concept anywhere in the schema. This is wholly new (requirement #7’s “one of three things, whichever is registered”).fluxx-extractorsubscribes toaccepted-file, notsplit-file, even thoughfluxx-document-splitter’s ownconfig.jsonalready declares anextractor-split-filesubscription onsplit-file— i.e., the SB topology partially anticipates this move already, but the extractor app code and its ownpubsub.config.jsonhaven’t been updated to match.- No component currently owns “what to do when there’s no classifier/splitter path” — i.e., a backward-compatibility/parallel-run story is needed if both the old (
accepted-file→ extractor direct) and new (accepted-file→ classifier → splitter →split-file→ extractor) paths must coexist during rollout.
3. Target State (New Workflow)
Key differences from current state, in requirement order:
- Upload endpoint unchanged (
fluxx-file-intake), except that theFileIDis now generated by Palantir and supplied on upload rather than generated server-side (see §3a). - Classifier calls Databricks classify endpoint — already true today; the new part is how it learns of completion, and that the call must now include the Palantir-issued
fileId. - No polling — Databricks publishes to a topic on completion; classifier subscribes instead of polling.
- Splitter behavior already matches the requirement (splits + publishes one event per file) — needs verification/regression testing against classifier’s new completion path, not new build.
- Extractor is triggered by
split-file(notaccepted-fileas today) and calls the existing Databricks extraction endpoint, including the relevantfileIdin the call (see §3a for whichfileId— parent vs. split child). - No polling — Databricks publishes extraction completion to a topic; extractor subscribes instead of polling.
fluxx-postal— not the extractor — contacts the registered Palantir endpoint, with the payload shape chosen from 3 registered options. This requires postal’s own DB table for registrations/delivery preference and a producer that actually publishes toto-send.
3a. FileID Ownership Change: Palantir-Generated GUID
New design direction: Palantir generates the FileID (a GUID/UUID) client-side at upload time and submits it along with the PDF. This becomes the canonical FileID for that document across the entire platform, and must be explicitly included in both the classification call and the extraction call made to Databricks — making fileId (not just the internal jobId/runId) a first-class cross-system correlation key.
What changes vs. today (confirmed in source):
4. Open Questions / Assumptions Requiring Decision Before Sizing Is Final
These materially affect sizing and should be confirmed with the Databricks/infra team and product owner before work starts. Each is flagged inline in the epics below as well.
5. Requirements List (Traceable to Source Bullets)
6. Epics & Sized Stories
Sizing scale used throughout:
- S (Small): ~1–3 days, single service, low risk, no schema change or an additive/backward-compatible schema change.
- M (Medium): ~3–5 days (up to ~1 week), may span 2 services or require a schema migration, moderate coordination/testing.
- L (Large): ~2+ weeks, cross-service, new infrastructure/data model, higher risk, may depend on external teams (Databricks/infra) or require a rollout/feature-flag strategy.
Epic A — Classifier: Event-Driven Classification Completion (Remove Polling)
Replaces ClassificationPollingOrchestrator with a reactive completion path.
Epic A total: ~1 L equivalent (6 stories, 1 spike)
Epic B — Extractor: Trigger from split-file + Event-Driven Extraction Completion (Remove Polling)
Epic B total: ~1 L equivalent (8 stories)
Epic C — Decouple Palantir Delivery From Extractor → Route via Postal
This is the biggest behavioral change: today DatabricksAIExtractor.processExtractionResult() calls PalantirApiClient.ingestExtractedFields() directly. That needs to become “publish a delivery-ready message”; fluxx-postal becomes responsible for the actual outbound call.
Epic C total: ~1 L equivalent (6 stories)
Epic D — Postal: Standalone Database for Registrations/Delivery Preferences
Directly implements requirement R8.
Epic D total: ~1 L equivalent (8 stories, includes net-new infra for the repo)
Epic E — Registration: Delivery Content-Type Preference & Cleanup
Epic E total: ~1 M-to-L equivalent (6 mostly-small stories)
Epic F — Shared Data/Schema Cleanup & Migration Hygiene (fluxx-sql-server)
Epic F total: ~1 S-to-M equivalent (4 small stories)
Epic G — File Intake: Confirm Fit for Palantir Entry Point (Low Risk)
Epic G total: ~1 M equivalent (7 stories) — was the lowest-risk epic; the FileID change adds real (but still modest) build work
Epic H — Status Check, Observability, Testing & Rollout
Epic H total: ~1 L equivalent (5 stories, includes one explicit L for the E2E harness)
7. Summary Rollup
Overall: 5 Large epics, 1 Medium epic, 1 Medium/Small epic, 1 Small-to-Medium epic — consistent with this being a cross-cutting architectural shift (poll → event-driven; extractor-direct → postal-mediated delivery; server-generated → Palantir-generated FileID) touching 7 of the 8 fluxx-* services plus the shared SQL schema. The three biggest unknowns that could swing sizing up further are Q1 (Databricks’ actual completion-notification capability — webhook support would add new inbound HTTP surface + auth work to both classifier and extractor), Q4 (whether a parallel/flagged rollout is required per client application, which roughly doubles the trigger-handling work in Epics A and B), and Q6 (whether split-child extraction/delivery correlates on the child’s own fileId or the original Palantir fileId, which affects the message contracts touched in Epics B and C).
8. Suggested Sequencing
- Epic G (G4–G6, FileID acceptance) — land Palantir-supplied
FileIDsupport influxx-file-intakefirst; every other epic’s correlation-key design (A3/A4, B4/B5, C1) depends onfileIdbeing reliably caller-supplied and validated at the point of entry. - Epic F (partial) + Epic E — schema groundwork (delivery content type, seed data) so downstream services have something to build against.
- Epic D — stand up postal’s DB and sync mechanism (can proceed in parallel with #2; no hard dependency).
- Epic C — wire extractor →
to-send→ postal → Palantir using the existing poll-based completion as the trigger for now (de-risks the biggest behavioral change — delivery ownership — independently of the polling removal). - Epic A and Epic B (completion-handling + Databricks request stories, including
fileIdpropagation) — once Q1 and Q6 are resolved, swap each service’s completion trigger from polling to event-driven and addfileIdto the classify/extract request payloads, reusing the delivery path already proven in step 4. - Epic B (split-file trigger rewire) — switch extractor’s inbound trigger from
accepted-filetosplit-file, feature-flagged per Q4. - Epic G (G1–G3, remaining verification/onboarding stories) — confirm/onboard file-intake fit beyond the FileID work already landed in step 1 (can happen any time, independent of the above).
- Epic H — observability and E2E testing threaded throughout, with the full harness (H3) finalized once steps 1–6 are functionally complete, then rollout (H4) client-application-by-client-application starting with Palantir.