Remote

Build: Secure Internal Opportunity-Monitoring Application (Python / Azure / React / HubSpot)

Lokasi klien: 🇺🇸 United States

Tentang pekerjaan

**Fixed-price project. Target go-live: November 30, 2026. Kickoff: mid-September 2026.**

What I need

I run a specialized accounting and advisory firm serving affordable housing and federally funded organizations. I need a secure, single-user internal web application that monitors a defined list of public sources, extracts individual opportunity and award records, classifies them against my service profile using configurable rules, scores them, presents them to me for review, and — only after I approve and the target has responded positively — creates deduplicated records in HubSpot.

This is a data-quality project disguised as a scraping project. The hard part is not fetching pages; it is producing records that are individually verifiable, correctly attributed to a real target organization, financially accurate against the source row, and correctly timed. Bids that treat this as “scrape 18 sites and keyword-match” will not be competitive.

## Scope

### 1. Source coverage and extraction

- 18 confirmed primary sources: 3 federal (USASpending REST API, HUD LIHTC property-level database, PHADA RFP listings) plus 15 state Housing Finance Agency sources. Full source list provided after initial screening.
- Formats include REST/JSON APIs, static HTML, JavaScript-rendered pages, PDFs (award rosters, reservation lists, ranking reports, application packages) and Excel workbooks (award and select lists). All must be first-class parser targets.
- Several sources publish one master document containing dozens or hundreds of projects. The system must split these into individual project records while retaining the master document as the shared evidence reference, plus the project’s specific page, table row, or record identifier.
- **Ingest-time snapshot.** Store a copy or full extract of every source document at retrieval. A source document that later moves, expires, or fails to load from its CDN must not invalidate records already ingested.
- Weekly scheduled runs plus manual per-source triggers.
- Bidders may propose additional sources with justification. Procurement aggregators may be proposed as a supplemental discovery layer, not a replacement for direct agency monitoring. Third-party reference/subscription sites are out of scope as primary sources.
- Describe how you handle bot mitigation (Cloudflare, datacenter-IP blocking), CDN-hosted documents, rate limiting, retries, and site-terms compliance. Do not assume residential proxying is acceptable.

### 2. Opportunity classes

- **Type 1 — direct procurement.** Solicitations I could bid on now.
- **Type 2 — demand signals.** Allocations, reservations, awards, Year 15/preservation events, and similar events where the *recipient* becomes a future client. Approval routes to research and enrichment, not a bid workflow.

Source type is assigned by me at the source level; the system does not infer or reclassify it. A rejected Type 1 record must be flaggable as a future demand signal for later research without changing the source’s classification.

### 3. Classification (rules-based only)

Rules-based only for the core Pass/Drop decision. No LLM-driven relevance decisions. AI use is acceptable only for optional field-extraction assistance or summarization, clearly labeled and never determinative.

**Pass = (sector context AND finance/service term) OR strong direct-service phrase.**

- Eligible finance/service terms: audit, audit readiness, accounting, bookkeeping, financial reporting, controller, CFO, internal controls, grant accounting, fund accounting, reconciliation, cost certification, draw, financial operations.
- Strong direct-service phrases: audit services, accounting services, bookkeeping services, fee accounting, financial reporting services, controller services, CFO services, grant accounting services, internal-control consulting, cost certification services.
- Sector terms — PHA, public housing, housing authority, LIHTC, affordable housing, multifamily — provide context only and must never produce a Pass on their own.

**Hard exclusions (never eligible, regardless of sector match):**

| Category | Reason |
|---|---|
| External audit and attest engagements | The firm performs no attest work. An “Auditor Services” solicitation seeking an external auditor is always ineligible, even though it matches “audit.” |
| Tribal governments, Tribally Designated Housing Entities, Indian housing authorities, NAHASDA, Indian Housing Block Grant — where that is the **primary context** | No experience in this market. Primary-context test only: an ordinary developer or nonprofit is not excluded merely for serving Indigenous residents or holding a community partnership. |
| Web development; graphic design | Outside service scope |
| Training, board/executive development, executive search, legal services, inspections, software, landscaping, grounds, janitorial, maintenance, vacancy prep, irrigation, energy/solar and net-metering procurement | Outside service scope |
| Homeownership, single-family, down-payment assistance, emergency shelter, landlord/tenant, small housing-counseling sub-grants | No development, financing, or finance-operations need indicated |
| Withdrawn, cancelled, expired, or unsuccessful records | No active demand |

Every record stores the matched terms and a plain-language Pass/Drop reason. Term lists, phrases, exclusions, weights, and thresholds are editable by me in the UI without a code deploy.

### 4. Timing and lead-time logic

- **Year 15 / preservation:** compute `Year 15 date = placed-in-service year + 15`, evaluated against a configurable lead window (default 12–18 months ahead). Outside the window is not a Pass. HUD LIHTC is historical property data and must not auto-pass; a record needs placed-in-service year, computed Year 15 date, window status, and an identified owner/developer/operator to become reviewable.
- **New award or allocation:** near-immediate follow-up.
- **Federal-funding growth and audit-readiness signals:** 6–8 months before the target’s fiscal year end.
- **Award year is a required per-record field**, not a source-level attribute. Sources mix allocation years within one list.
- **Award recency rules** (configurable): current year active; prior year selective with status verification; two years low priority unless large, recurring, or tied to an active development; three years or older excluded from the active queue and retained as account history only.
- Type 1 records store the submission deadline and auto-flag when it passes.

### 5. Strategic scoring model

Formula: `(3 × A) + B + (2 × C) + D`. **Maximum 25, minimum 7.**

| Component | Weight | Definition | Point values |
|---|---|---|---|
| **A — Service-line value** | ×3 | The service line the opportunity most likely maps to | Fractional CFO 4; Audit readiness 3; Operations transformation 2; Bookkeeping 1 |
| **B — Entity size** | ×1 | Size of the target organization. Ordering is deliberate — the ICP is mid-market, so Mid outranks Large | Mid 3; Large 2; Small 1 |
| **C — Industry recognition** | ×2 | Recognition of the target entity within its own industry, not general fame | National 3; Regional 2; Local 1 |
| **D — Entity type** | ×1 | Type of the awardee or target organization | AH developer/operator 4; Nonprofit 3; PHA 2; HFA 1 |

Rules governing the model:

- **A, B, C, and D are scored on the awardee or target organization — never on the publishing agency.** An allocation list is a source, not an account.
- **Score completeness is a separate stored and displayed field** from the total score, so a low score caused by missing data is distinguishable from a genuinely low-value opportunity.
- All point values, weights, and resulting thresholds are editable by me in the UI without a code deploy.
- Scoring never overrides classification. A hard-exclusion record cannot be rescued by a high score.

**Non-scoring prioritization fields.** These are captured and filterable, but are not components of the score:

- **Service-line tag:** Audit Readiness, Development Accounting, Financial Operations Transformation, or Strategic Advisory.
- **Signal type:** new award or allocation; Year 15 or preservation window; Single Audit finding; REAC or inspection failure; open finance-leadership seat; RFP or procurement; federal funding activity.
- **Target-profile indicators:** approximate entity count (sweet spot roughly three to eight), number of active LIHTC or affordable-housing projects, and evidence of limited in-house accounting depth. Developers and operators are prioritized ahead of nonprofits.
- **Source and relationship context:** which source produced the record and whether the target is an existing relationship, referral-adjacent, or cold. Useful for sequencing; not part of the score.
- **Actionability** is enforced through the research-ready / outreach-ready gate in Section 7, not through the score.

### 6. Record quality — non-negotiable acceptance conditions

These are the requirements most likely to be underestimated. Read them carefully before pricing.

**Entity resolution.** Three distinct fields are required:

| Field | Content |
|---|---|
| Opportunity | Project or development name, RFP title, award, or funding event |
| Entity | Sponsor, developer, owner, applicant, PHA, nonprofit, grantee, or operating organization |
| Parent entity | Operating parent where the applicant is a project LLC or special-purpose entity |

The project name must never be copied into the Entity field. Worked examples of correct resolution: Hunt Ridge Apartments → Community Housing Partners; Westside Phase I – Phase 1A → Chattanooga Housing Authority (with Columbia Residential as development partner); DESC Morrison Preservation → Downtown Emergency Service Center; Belvedere Terrace, LP / Newport SW GP LLC → Newport Partners as the operating parent; Royal Oaks → Ingerman Development Company LLC.

**Contact capture.** Where the source names a primary contact, phone number, email, ownership principal, or development partner, those fields must carry through to the record. Several sources supply them today and they are commonly dropped.

**Record-specific evidence.** Every record needs a reference that identifies *that* record: a project-level URL, or a specific page/row/identifier within a shared document. A generic dataset landing page, statewide press release, or program announcement is acceptable only as supplemental context and must never be assigned as the primary evidence link across multiple records.

**Link validation.** Validate every source URL at ingestion and on a recurring schedule. Failures are labeled **Broken Link / Needs Refresh**, excluded from the approval-ready queue, and surfaced for remediation. Store HTTP status, last-checked timestamp, and the archived source extract.

**Labeled financial fields.** A single “Amount” column is not acceptable. Amount types that must be distinguishable: LIHTC credit request, LIHTC reservation, annual LIHTC allocation, final award, NHTF award, state credit, HOME, Housing Trust Fund, total development cost, federal award value, federal obligation, federal outlay, and RFP or contract value. Requests stay labeled as requests until a final allocation source confirms the award.

**Amount tie-out and row alignment.** Extracted amounts must reconcile to the source row. Row misalignment is a known failure mode. Acceptance testing includes a per-source numeric tie-out on a reviewed sample, and the build must include an automated row-integrity check (project name, sponsor, and amount drawn from the same row).

**Award status and pool detail.** Capture and surface Select / Select–NP Set Aside versus Non-Select / Non-Select–Tie; Funded versus ranking-only; waiting-list; asterisked conditional reservations; and pool or section identity, including separately labeled unranked sections such as “Unranked — Noncompetitive or Awaiting Other Funding Commitments.” An unranked or non-selected record must never display identically to a funded one.

**Deduplication and account grouping.** Project phases (e.g., Phase 1A and 1B), twinned 9%/4% structures, sibling projects from the same sponsor at different addresses, and re-published rosters must not become separate outreach targets. Grouping is at the account level (developer, sponsor, or agency), with projects as child records.

**Minimum-materiality filters.** Configurable award-size floor and a repeat-recipient rule, so small one-off grants are excluded unless the recipient shows recurring or larger awards.

**Conflict alerting.** When an extracted title, deadline, issuer, solicitation number, amount, or scope conflicts with the underlying official source, raise a validation alert. The official issuer document controls.

### 7. Review workflow and status taxonomy

- Review queue with a per-record detail view showing extracted fields, matched terms, total score and score completeness with the A/B/C/D breakdown visible, timing calculation, evidence link and link health, labeled financial fields, award/pool status, and the identified entity and parent — without requiring me to reopen a multi-page roster to validate one project.
- Statuses: **Approved**, **Rejected**, **Hold / Needs Research**, **Signal / Needs Research**, **Broken Link / Needs Refresh**, **Conditional — Confirm Award Status**, **Deadline Passed**, **Future Demand Signal (flagged from a rejected Type 1)**.
- Two-stage readiness gate: **research-ready** once the source and entity are confirmed; **outreach-ready** only after the operating organization, relevant contact, current role, and company domain or email pattern are verified, with contact source and confidence recorded.
- Bulk approve/reject and bulk status assignment at source level and selected-row level, where “approve” means “route to enrichment.”
- Full audit trail: who changed what, when, and why. Rejected records are retained, never deleted.

### 8. Enrichment, HubSpot, and Karbon

- **Cost-controlled enrichment.** Contact enrichment must be batched and require my advance approval of each batch, with per-batch and running cost visibility. No open-ended API spend.
- **Access control on contact data.** Vendor-response and RFP-poster contact details are viewable only after login.
- **HubSpot entry rule.** Contacts are not created in HubSpot until the record is approved **and** a positive response has been received. Placeholder contacts are prohibited. Approved-but-unconverted records live in the application, not in HubSpot.
- HubSpot environment: Starter Customer Platform (Marketing, Sales, Service, Content, Data Hub Starter), 1 core seat, 1,000 marketing contacts, 500 HubSpot credits. No custom pipelines, properties, or workflows exist yet — scope against a fresh Starter environment and stay within Starter API and object limits.
- Scope controlled, deduplicated creation of company, contact, deal, and task records at conversion, with conflict checking against existing records.
- **Karbon integration is in base scope**, not an option.

### 9. Architecture, security, and operations

Reference stack (defend or redirect it in your proposal, with reasoning): Python/FastAPI parsers for HTML, XML, PDF, and Excel; Azure Functions on a weekly schedule with manual per-source triggers; Azure SQL for storage; React dashboard for review and approval; Azure Key Vault for secrets.

- Deployed into **my** Azure subscription and my repositories. I own all code, IP, and data at delivery.
- Single-user authentication with MFA, least-privilege service identities, no credentials in code or config.
- No production data, credentials, source extracts, contact information, or system access may be copied to personal devices, personal repositories, unapproved SaaS tools, or AI-model training environments. Any access by subcontractors, including offshore personnel, requires prior written approval and must use approved, access-controlled systems.
- Per-source run logging, failure alerting to email, and a per-source health view: last successful run, records extracted, pass rate, link-failure rate, field-completeness rate, and average score completeness.
- Deliverables include source-code handover, deployment runbook, an operations guide written for a non-engineer, and a documented procedure for adding a source or editing rules and score values without developer involvement.

### 10. Operating assumptions

- Roughly 50 approved opportunities per year. Single user. Low volume, high precision.
- **A 100% pass rate on a source is a failure signal, not a success signal.** Approval status must carry information.
- All approved contacts are retained for nurture even though only a minority convert.
- Forward-only monitoring at launch. Historical backfill of already-published awards must be priced separately as an optional Phase 2 with its own timing assumptions.

## Acceptance and payment

Milestone-based, with a deposit and milestones tied to demonstrated delivery. **Source-level acceptance testing is required before production acceptance, and every one of the 18 sources must be evidenced individually — including API sources that are easy to assume are fine.** Per source, acceptance requires:

1. Every approval-ready record resolves to a working, record-specific evidence reference.
2. Zero records where the Entity is a copy of the Opportunity name; parent entity populated wherever the applicant is a project LLC or SPE.
3. Contact fields populated wherever the source supplies them.
4. Pass records contain both a housing/program term and a finance/service term, with matched terms shown; no record passing on a sector term alone; no attest or hard-exclusion record passing.
5. False-positive rate on a reviewed sample within an agreed cap, and pass rate within an agreed band, both reviewed by me.
6. Numeric tie-out: sampled amounts match the source row, correctly labeled by amount type, with no row misalignment.
7. Award status, pool/section, conditional flags, and award year populated and computed correctly where the source supplies the inputs.
8. Scores computed correctly against the published point values, scored on the target entity rather than the publishing agency, with score completeness reported separately.
9. Duplicate phases, twinned deals, sibling projects, and repeated rosters grouped rather than duplicated.

Propose a short pilot on three sources of my choosing — one API, one PDF/Excel roster, one JavaScript-rendered page — before the full build, priced as its own milestone. Include a warranty/bug-fix window after go-live.

**Reference field set.** The richest sources currently available return, per project: record/LIHTC number, project name, full address, county, sponsor or development team, ownership principal, named contact with phone and email, cycle or pool, affordable and total units, project type, target population, construction type, reservation or award date, application number, award status, underwriting status, and separately labeled award amounts. That is the benchmark field set. Where a source supplies these, the record must contain them.

## Confidentiality and work-product protection

This project involves non-public business, technical, operational, and commercial information. Bidders must treat all materials received during the proposal process as confidential and use them solely to prepare a proposal.

The selected vendor will be required to execute Kearney & Partners LLC’s confidentiality and non-disclosure agreement before receiving system access, detailed implementation materials, source configurations, sample data, credentials, or other confidential information.

The selected vendor’s agreement will also require that all code, configurations, source extracts, data models, documentation, deliverables, modifications, and other work product created for this project are confidential and are owned exclusively by Kearney & Partners LLC upon payment. The vendor may not reuse, disclose, publish, sell, train AI systems on, or provide the resulting product or related confidential information to any third party without Kearney & Partners LLC’s prior written consent.

Any subcontractor or team member given access to project information must be bound by written confidentiality obligations at least as protective as those in the selected vendor’s agreement. No subcontracting, offshore access, or transfer of project data is permitted without prior written approval from Kearney & Partners LLC.

Confidentiality obligations survive the proposal process and, if selected, the end of the engagement.

## What I am not sharing at this stage

Budget range — bidders price on the merits.

## To apply

Please address each of the following. Proposals that skip these will not be reviewed.

1. A comparable system you have shipped that extracted structured records from government PDFs or Excel rosters. What broke, and how did you handle it?
2. How you would guarantee record-specific evidence for a source that publishes one master PDF containing 74 projects.
3. How you would resolve the sponsor or developer entity, and its operating parent, when the source lists only a project name or a single-purpose LLC.
4. How you prevent row misalignment when parsing multi-column PDF tables, and how you would prove amounts tie to the source row.
5. How you would populate the four scoring components — service-line value, entity size, industry recognition, and entity type — from source data, and how you would represent a component you cannot determine.
6. Your approach to bot mitigation, CDN-hosted documents, and JS-rendered pages, and where you draw the compliance line.
7. Your proposed milestone plan against a mid-September start and November 30 go-live, with dependencies that could move the date.
8. Team composition, named individuals, and who writes the parsers.
9. Fixed price, including the three-source pilot and the optional Phase 2 backfill priced separately.

**Confidentiality requirement:** The selected vendor will be required to sign Kearney & Partners LLC’s confidentiality and non-disclosure agreement governing both confidential project information and the resulting work product.