Funding Monitor

About

Funding Monitor tracks EU / EU-entity-eligible funding opportunities (national portals, EU-wide calls, cascade/FSTP calls, PRIMA, Interreg), extracts structured details with AI, and ranks them against your organizations' profiles and preferences. No US federal/state/foundation grants are in scope.

Version: 0.5

Roadmap

Last updated: 27/07/2026

future (planned)

  • The items below were originally sketched as two separate near-term milestones ("0.4" and "1.0 — commercial platform") before 0.5's infrastructure work shipped ahead of them. Folded into one backlog now that there's no fixed next version number attached — these are the acknowledged next priorities, not dated commitments.
  • GOAL (commercial platform): turn this from a single-tenant tool into a real multi-tenant product — sized against ~200 CONCURRENT users. This is a foundational rearchitecture (auth + tenancy touch nearly every route), not an incremental feature. Nothing in this section is built yet.
  • Authentication: real login (currently none — the live site has no auth wall at all, anyone who finds the URL can reach every page and every action)
  • A role-BUILDER, not just fixed tiers: Platform Admins define roles by ticking which specific tools/features that role can access (checkboxes against real permissions — "manage sources," "override matches," "manage billing," "invite users," "access AI provider settings," "run bulk actions," etc.), rather than being stuck with a hardcoded 3-tier list. Ships with a couple of sensible default role templates (Platform Admin / Organization Admin / Organization User) so most organizations never need to touch the builder, but anyone with unusual needs (e.g. a read-only auditor role) isn't stuck
  • Consultancy model: a single account that manages MULTIPLE organizations (e.g. a consultancy handling several client profiles) — needs a many-to-many user↔organization relationship, not the current implicit "whoever's running the app owns every profile" model, plus a way to switch/scope which organization's data is in view
  • Data model changes this implies: a User table, a Role/Permission table (see role builder above), an organization-membership table (many-to-many), and every existing query (Opportunities, Matches, Sources, Overrides) scoped by the requesting user's accessible organization(s) and permissions instead of returning everything unconditionally
  • Admin-configurable settings instead of hardcoded constants — starting with the matching-weight blend (AI_SCORE_WEIGHT/TAG_OVERLAP_WEIGHT in matching/engine.py, currently 65/35 fixed in code) and extending to things like candidates-per-check defaults, taxonomy edits, and which sources are shared vs. per-tenant
  • Commercial-readiness: billing/subscription handling, usage limits per plan, and deciding what's shared infrastructure (sources, the taxonomy, AI provider config) vs. what's genuinely per-tenant (organization profiles, matches, overrides, workflow state)
  • IMPORTANT sizing point: AI compute does NOT scale with USER count — Opportunity rows are already global/shared (extracted once, used by every tenant) and Match rows are keyed per (opportunity, organization profile), not per user. 200 concurrent users spread across a modest number of organizations is a far smaller AI workload than 200 separate organizations would be — cost/throughput planning should size against expected ORGANIZATION count, not user count
  • A real cloud AI provider (Claude/OpenAI) as a proper fallback, not just a nice-to-have — the live site currently depends on the office's own Ollama being reachable over the internet (static IP + port-forward + firewall rule), which is a genuinely fragile chain (office internet, power, or IP changes would silently break AI extraction on the live site)
  • Monitoring/alerting stack — nothing beyond manual server-admin-GUI checks exists yet; no automated uptime/error alerting
  • Finish the off-VPS backup story — the server-side pull mechanism (restricted, chrooted, read-only SSH account) is ready, but the actual scheduled pull job on the user's own backup device still needs configuring on that device
  • Security hardening beyond the deployment basics already in place: rate limiting on login and on AI-triggered/expensive endpoints (stops one runaway client or bug from generating a large, unexpected AI bill), an audit log for role/permission/billing changes and match overrides, and per-organization AI usage/cost tracking (useful for spotting anomalies early and for usage-based pricing later)
  • A staging environment to rehearse risky changes (schema migrations, auth rollout) somewhere reversible before they touch the live database
  • Partner recommendations from an Odoo contact export (companies + tags) matched against each call's domain/technology tags — needs a decision on live sync vs. CSV export and a tag-mapping scheme between Odoo's tags and this app's taxonomy
  • Document/template link extraction for non-eu_portal (HTML/RSS) sources — currently eu_portal-only, since only its conditions text is parsed with links preserved
  • Per-source candidate-link tuning for PRIMA/Interreg (news-heavy sites without a clean listing→detail-page structure produce a lot of AI calls on non-call pages)
  • Scheduled unattended periodic source checks
  • Claude/OpenAI providers exercised end-to-end alongside Ollama
  • Cross-source duplicate detection (the same call sometimes appears on more than one portal)
  • Email/notification alerts on new high-match opportunities
  • Proposal-drafting assist
  • Calendar view of upcoming deadlines
Agreed execution order — what we do first

Phase 1 — Auth & multi-tenancy (the big rearchitecture; build on the already-live 0.5 infrastructure, not on SQLite)

  • User model + real login (bcrypt/argon2 password hashing, sessions)
  • Role/Permission model + role-builder admin tool — ships with default templates, supports custom roles
  • Org-membership table (many-to-many — supports both single-org users and a consultancy account managing multiple client organizations)
  • Scope every existing query (Opportunities, Matches, Sources, Overrides) by the requesting user's accessible organization(s) and permissions

Phase 2 — Commercial mechanics

  • Billing/subscriptions (Stripe or similar), usage limits per plan
  • Admin-configurable settings (matching weights, taxonomy edits) instead of hardcoded constants
  • ToS/privacy policy/GDPR compliance (this handles EU business data)
  • Self-serve organization onboarding flow

Phase 3 — Scale validation & launch prep

  • Load-test at ~200 concurrent users
  • AI-cost strategy decision: office Ollama vs. a real cloud fallback — remember AI compute scales with ORGANIZATION count, not user count
  • Security review before opening to real customers
  • Pricing model decision (per-org / per-user / per-match)

First concrete step: Design the User/Role/Permission/org-membership data model and the role-builder UI before writing any auth code — this is the actual starting point now that Phase 0's infrastructure (containers, Postgres, the priority queue, live TLS) already shipped in 0.5.

v0.5 (current)

  • Moved from a local-only tool to a live, containerized deployment: https://funding.ecect.eu — real HTTPS (Let's Encrypt), deployed onto shared self-hosted infrastructure (Docker + Nginx Proxy Manager) alongside another project, reusing its existing reverse-proxy/TLS tooling rather than building a new stack
  • Database moved from SQLite to PostgreSQL — all real production data (opportunities, matches, sources, organization profiles, overrides, settings) migrated and verified row-for-row; local SQLite + the original in-process threading remain fully supported for local development, unaffected
  • Background jobs moved to a real priority queue (Redis + RQ) in the deployed environment: three queues ("high"/"default"/"low"), always drained in that order — one-off user-triggered actions (add-by-URL, PIF upload, recompute matches, test source) get priority over routine bulk work (the full EU-portal sync, the multi-model benchmark sweep). Replaces the old "any job blocks any other job equally" behavior
  • Automated nightly database backups with an actually-tested restore (not just an assumption it would work) — plus a dedicated, tightly restricted pull mechanism (chrooted, read-only, key-auth-only SSH account) so backups can be pulled off the server on a real schedule
  • The office's local Ollama instance is now securely reachable by the live deployment (scoped firewall rule + router forwarding), so AI extraction works on the hosted site using existing local hardware rather than requiring a cloud AI subscription on day one
  • Two real cross-database bugs found and fixed during the move to PostgreSQL: a SQLite-only performance tweak (`PRAGMA journal_mode=WAL`) that was firing on every database connection regardless of which database was in use, and a startup race between the web process and the background-job worker both trying to set up the database schema at once

v0.3 (shipped)

  • EU Funding & Tenders Portal: fixed a pagination bug that silently capped discovery at 500 of ~750+ live calls (missing exactly the near-term-deadline ones); results now sort soonest-deadline-first instead of newest-start-date-first
  • EU portal opportunities now carry real structured fields straight from the portal's own API (not AI-guessed): Programme, Call identifier, Type of action, Deadline model, Planned opening date, Model Grant Agreement type, and Submission status (Open/Forthcoming) — plus a "Load more details" button to backfill older rows
  • Fixed a bug where a candidate's identifier was re-derived from its URL instead of carried from discovery, which silently failed on ~78% of EU-portal candidates in one observed run; also fixed the source's "last checked" timestamp permanently showing "never" whenever any candidate in a run failed
  • Deadline-range filter, results-per-page control (100/250/500/1000), and a configurable per-source "candidates processed per Check now run" cap (was a fixed 60) so a full catch-up run can process everything in one go
  • Domain (~30 EU-portal topic categories) and Technology (Cascade Funding Hub's own taxonomy) tagging — AI-classified on every opportunity, human-picked (colour-coded chip picker) on organization profiles — plus a Field-of-expertise picker for profiles. Both feed into filtering and into the AI match-scoring prompt
  • Matching-prompt rewrite so domain/technology tag overlap (including a profile's more specific tag matching an opportunity's broader one) is explicitly weighed in the score and named in the rationale
  • Fixed two real hard-filter bugs found via user-made overrides: eligibility phrased as plain "EU countries" (not spelled out as "European Union"/"member state") and "EU entities" (a blanket org-type allowance, not a specific type) were both silently excluding genuinely-eligible organizations — affected 74 of 720 existing match rows
  • Human-in-the-loop match override: correct any match's score by hand with a reason, without ever losing the system's own original score/rationale; a dedicated /overrides/ page reviews every correction across the whole app and flags rule-filter corrections specifically as likely code bugs; AI-scored matches also feed a profile's past corrections back into future scoring prompts as calibration
  • Star/favorite flag, a "Starred only" filter and "Starred first" sort
  • Workflow tracking per opportunity — New → Viewed (automatic) → In progress → Decided (manual) — with a filter row and a quick "In progress" link
  • Best Match column/sort: defaults to best-match-first (was deadline-first), and now shows every organization's score, not just the top one
  • Document/template links (application form, evaluation form, MGA, guidance annexes) extracted from the EU portal's own conditions text and shown on the opportunity detail page — not yet available for non-eu_portal sources (see 0.4)
  • Light/dark theme toggle, defaulting to light regardless of OS preference (previously dark-preference systems had no way to switch within the app)
  • Add an organization profile from an uploaded Partner Identification Form (PDF or Word) as an alternative to crawling a website — same AI drafting and human-in-the-loop review as a URL crawl, including auto-tagged domains/technologies/expertise. The full extracted document text is kept permanently on the profile as a reference, viewable on the review screen
  • Update an EXISTING profile from a newly-uploaded PIF (not just create a new one) — re-drafts every field in place and always drops back to "pending review" so the redraft gets a fresh look before it's trusted for matching again
  • "Add organization" consolidated to one entry point with a website/PIF toggle, instead of three separate buttons/pages
  • Richer AI extraction: description and past-experience prompts now ask for real detail (one paragraph per named project, not one compressed sentence) instead of a generic summary, since domain/technology auto-tagging is grounded in exactly this text
  • Weighted matching: AI-scored matches now blend the AI's semantic judgment with a deterministic domain/technology tag-overlap score (65% AI / 35% tag overlap by default), with the breakdown shown in the rationale — the "yes/no eligibility gate, then a weighted score" structure made explicit and transparent instead of one opaque AI number
  • Review-profile page redesign: grouped into Identity / Description & experience / Domains-technologies-expertise sections, 2-column layout for compact fields, and a live "selected tags" summary bar above each picker (with one-click removal) so you don't have to hunt through ~30 collapsed domain categories to see or edit what's already chosen

v0.2 (shipped)

  • Deadline-urgency status — Expired / Act now (≤30d) / Prepare now (30-90d) / Future (90d+), computed live against today's date, plus a manual Archive override
  • Opportunities list: checkbox filters for Status, Matching level (0-20/20-50/50-70/70-100%/not-yet-scored) and Source, a free-text Search box, and Sort (deadline/match%/budget/newest)
  • RSS/Atom feed support for sources, as an alternative to HTML-listing crawling — more reliable candidate discovery on sites that offer a feed
  • "Test source" dry run: verifies a source is configured correctly (finds candidates, confirms a sample look like real calls) before committing to a full, possibly multi-minute "Check now"
  • LAN access — reachable from other devices on the network, not just this machine
  • Matching-engine fix: eligibility checks now understand synonyms (non-profit/NGO, SME, EU member states, etc.) instead of requiring literal text matches — a profile could previously score 0% on everything if its org type/country was phrased differently than the source text

v0.1 (shipped)

  • Manual "Check now" ingestion from monitored sources, with a live progress bar
  • Five seeded sources: Cyprus Funding Programmes Portal, EU Funding & Tenders, Cascade Funding Hub, PRIMA, Interreg Euro-MED
  • Ollama (local) AI provider, with Claude/OpenAI available in Settings
  • Human-in-the-loop organization profile creation from a multi-page crawl (homepage + About/Team/Projects-style pages) synthesized into an AI research brief before structured extraction
  • Hard-filter (eligibility, budget, call type, duration, intensity) + AI Matching% scoring
  • Manual add-opportunity-by-URL
  • Background jobs for every crawl/extraction step, so the UI never blocks