Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
Tender Tool turns your company documents, people and past-project evidence into SANRAL's complete technical and financial envelope packs - checked page by page against the tender's own rules. No AI bl
BusinessTypeScript · PythonGitHub @SarelJvR2024OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Tender Tool turns your company documents, people and past-project evidence into SANRAL's complete technical and financial envelope packs - checked page by page against the tender's own rules. No AI blabber, nothing missing, nothing expired.
Taken from the repository README
Loading the full README.
Read the full README ↗Multi-tenant SaaS for South African tender preparation (SANRAL, ACSA, SASSA), built first around
Sarel's own tenders. See docs/specs/Tender-Tool-Claude-Code-Handover.md for the build brief,
phase order and architecture requirements — read it before changing anything here.
docs/specs/ — the source-of-truth specs, pulled in verbatim from the Drive folder "Tender Tool":
Tender-Tool-Claude-Code-Handover.md — build brief and phase order. Read first.SANRAL-Tender-Automation-Specification.md — the SANRAL workbook-filling spec (sections 1–9,
the 12-point verification checklist V1–V12, open issues, questions for Sarel).SANRAL-Appendix-A-Source-Code.md — the same engine scripts in engine/, as markdown, for
reference against the spec's own commentary.Tender-Tool-Competitor-Feature-Deep-Dive.md — competitor research and the phased feature list.engine/ — the SANRAL workbook-filling engine, extracted from Appendix A (unmodified) plus
fingerprint.py (Stream 1, new).templates/samples/ — real blank SANRAL "Conventional Consultant Tender" templates, for testing
the engine against. SHA-256 verified against the hashes recorded for these files in Drive.fingerprints/ — stored template-family fingerprints (Stream 1 baselines). Generated by
engine/fingerprint.py, not hand-written.Sarel's rule: "There's always a chance a tender template has changed, so we must always check first." Run this before ever filling a workbook:
python3 engine/fingerprint.py <template.xlsm>
First run for a template family stores the baseline. Later runs compare against it and print
exactly what changed on any mismatch — sheet names/order, dropdown count per sheet, named ranges,
per-sheet cell-layout hash, macro presence/hash, or the whole-file hash. See the module docstring
in engine/fingerprint.py for the documented limitation (it fingerprints occupied cell references,
not lock/formula status — a tighter version is future work).
Open question for Sarel: running this against the 5 real Conventional templates supplied,
every file except the two R.334-030-2025.1F submissions (ran/ran1) flagged a macro-hash
mismatch against the first one seen. ran and ran1 are two submissions for the same contract
and matched exactly; R.343, R.352 and R.394 are each a different contract and each has a
different vbaProject.bin hash from the baseline (R.343 also differs in TEND 1X cell layout).
This may just mean SANRAL's own export re-compiles the VBA project (embeds a fresh timestamp/GUID)
per contract even when the macro source is identical — or it may mean these aren't all the same
template version. Either way the tool is refusing to guess, as designed; it needs a decision on
whether macro hash should be part of the family fingerprint or compared separately from the rest.
engine/discovery/list_tenders.py — pulls the full open-tenders list via the site's own
DataTables AJAX endpoint (confirmed: 137+ tenders, not the 10 the rendered page shows). No
auth, no personal data.engine/discovery/detail.py — per-tender metadata (file size/count, create/last-updated
dates) from the public detail page. No auth, no personal data.engine/discovery/download_documents.py — actually fetches a tender's document pack. This
does submit personal data (full name, company, phone, email) through the site's real
"Download Documents" form, via a real browser (Playwright/Chromium) clicking the real button —
not a captcha-solving workaround, just normal use of a reCAPTCHA v3 (invisible) protected form.
Requires --fullname/--company/--phone/--email explicitly; refuses to guess at identity.engine/discovery/run_discovery.py — the daily run: fetches the full list + detail metadata
for every open tender (free, no identity data), diffs against the previous run, and only
submits the download form for tenders that are new or changed since then — not all ~137
every day. Unzips each downloaded pack and runs fingerprint.py on every .xlsm inside.
Identity comes from a local --contact-file (see config/contact.json.example), never
committed, never hardcoded.Compliance check done 2026-10-15: robots.txt allows all paths for all agents; the published Terms & Conditions cover only copyright/disclaimer/linking — nothing about automated access.
.xlsm here — it drops the form controls and data validations.