The engineering a recruitment service should be willing to show you. Matching logic, consent evidence, encryption, deletion — from the systems behind flowgt.co.nz, published so you can verify instead of trust.
Code: AGPL-3.0 or Commercial Docs: CC BY-NC-ND 4.0 Law: NZ Privacy Act 2020 Email: UEMA 2007
A recruitment service holds the most personal documents people have: their CVs, their job searches, their outcomes. Every agency says it handles these carefully. Saying it is cheap.
Trust cannot be asserted. It can only be verified. So the parts of our engineering that decide whether we deserve trust — how consent is recorded, how unsubscribe works, how CVs are encrypted, how matching ranks a person's opportunities, when data is deleted — are published here, with the New Zealand law they answer to quoted clause by clause.
- 🧑💼 If you are an employer — read how roles are matched and ranked before they ever reach a candidate.
- 🧑🎓 If you are a candidate — read exactly what happens to your data, and check our claims against the statutes yourself.
Five principles, enforced as acceptance criteria on every file:
| Principle | What it means here | |
|---|---|---|
| 🔒 | Structure over promise | A rule that matters becomes a schema constraint or a test — never only a sentence. Consent is a verbatim record, not a boolean. |
| 🪪 | Evidence, not assertion | UEMA s 9(3) puts the burden of proof on the sender — so every consent row can answer "what exactly did they agree to?" years later. |
| 🔇 | Silence must be distinguishable from failure | "We checked and there was nothing" ≠ "we failed" ≠ "we never ran". Three different rows, never one. |
| 🧹 | Clean | No personal data, no credentials, no internal traces. Verified before every publication, not assumed. |
| ⚖️ | Neutral | Legal claims quote the statute, with a source link, a verification date, and a credibility grade. Open questions stay marked open. |
mindmap
root((FlowGT<br/>Open Reference))
🎯 matching/
roles.js — the ranking logic
ARCHITECTURE.md — design record
digest-runs.sql — the honest ledger
🛡️ privacy/
unsubscribe.js — one click, no login
no-member-data.py — the data gate
schema/
consent-subscriptions.sql
consent-v2-migration.sql
cv-encryption.sql
retention.sql — the 24-month promise
📚 compliance/
UEMA 2007 — email law
Privacy Act 2020
Fair Trading Act
candidate fees · e-signature
immigration advice · platform terms
⚖️ LICENSING.md — the Qt model
Every arrow below exists because a law or a failure mode demands it.
flowchart TD
A[👤 Member turns email ON<br/>in their own portal] -->|verbatim sentence +<br/>time + source recorded| B[(🪪 Consent evidence<br/>job_subscriptions)]
B --> C{⏰ Weekday?<br/>consent says weekdays only}
C -->|weekend| Z1[🚫 Nothing sends]
C -->|weekday| D[🎯 Match & rank<br/>relevance ORDERS, never drops]
D --> E{Fresh roles?}
E -->|none| Q[😴 outcome: quiet<br/>recorded — not a failure]
E -->|yes| F[📧 Send digest<br/>≤25 per bucket]
F --> G[(📒 Ledger<br/>digest_runs + snapshot)]
F --> H[🔗 One-click unsubscribe<br/>in every footer]
H -->|no login required| I[(🔕 Sticky opt-out<br/>re-consent needed to return)]
G --> J[🖥️ Member portal shows<br/>send-time snapshot<br/>email & page never disagree]
classDef consent fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20
classDef ledger fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef stop fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c
classDef action fill:#fff8e1,stroke:#f9a825,stroke-width:2px,color:#795500
class A,B consent
class G,I,J ledger
class Z1,H stop
class C,D,E,F,Q action
erDiagram
ACCOUNTS ||--o| JOB_SUBSCRIPTIONS : "one consent record"
ACCOUNTS ||--o{ DIGEST_RUNS : "one per send attempt"
DIGEST_RUNS ||--o{ DIGEST_RUN_JOBS : "send-time snapshot"
ACCOUNTS ||--o{ CV_DOCUMENTS : "encrypted, versioned"
CV_DOCUMENTS ||--o{ CV_REVIEWS : "audited AI ledger"
ACCOUNTS ||--o| RETENTION_NOTICES : "30-day warning"
RETENTION_LOG }o..|| ACCOUNTS : "hash only, after deletion"
JOB_SUBSCRIPTIONS {
text consent_text "the exact sentence agreed to"
int consent_at
text unsub_token "one click, no login"
int unsubbed_at "sticky"
}
DIGEST_RUNS {
text outcome "running | sent | quiet | failed"
text trigger_kind "scheduled never impersonated"
int n_shown "NULL on failure, never 0"
}
CV_DOCUMENTS {
text ciphertext "AES-256-GCM"
text consent_text "recorded at upload"
}
RETENTION_NOTICES {
int notified_at
int delete_after "notice + 30 days"
}
RETENTION_LOG {
text email_hash "sha256 — no identity kept"
int deleted_at
}
The privacy page promises it; this machinery delivers it
(privacy/schema/retention.sql):
flowchart LR
A[🕐 Any sign-in<br/>or activity] -->|resets| B[⏳ 24-month clock]
B -->|23 months silent| C[📨 Notice email:<br/>30 days' warning]
C -->|one sign-in| B
C -->|30 more days<br/>of silence| D[🗑️ Deletion<br/>cascades everywhere]
D --> E[(🧾 Ledger keeps a<br/>one-way hash only)]
classDef ok fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20
classDef warn fill:#fff8e1,stroke:#f9a825,stroke-width:2px,color:#795500
classDef del fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c
class A,B ok
class C warn
class D,E del
- ✅ Any activity resets the clock — one sign-in is enough.
- 📨 Nothing is deleted without warning — a notice goes out 30 days ahead.
- 🧾 After deletion, only a hash remains: keeping the identity of the person you deleted, to prove you deleted them, is a contradiction.
| Folder | For whom | Contents | |
|---|---|---|---|
| 🎯 | matching/ |
Employers & candidates | The scoring logic, the design record, and the delivery ledger — including why relevance orders and never drops |
| 🛡️ | privacy/ |
Candidates & anyone we email | Consent evidence, unsubscribe, CV encryption, the data gate, retention |
| 📚 | privacy/compliance/ |
Anyone checking our claims | The NZ legal reference library — verbatim statutes, source links, verification dates, credibility grades |
| File | Governs | One-sentence verdict |
|---|---|---|
uema-2007-email.md |
📧 Commercial email & SMS | No B2B exemption; burden of proof is on the sender |
privacy-act-2020.md |
🪪 CVs, contact data | Collect only what's relevant; destroy on schedule; IPP 3A governs indirect collection |
candidate-fees.md |
💰 Revenue model | Charging candidates anything is illegal; money comes from employers only |
fair-trading-act.md |
📢 Website claims | Only verifiable claims may be published |
immigration-advice.md |
🛂 Conversations | No immigration advice, ever — it requires a licence we do not hold |
e-signature.md |
✍️ Contracts | Electronic signatures fully valid (CCLA 2017 ss 226–228) |
platform-terms.md |
🔌 Data sources | Only channels whose purpose is to be read |
Nothing here is legal advice — each file carries its own disclaimer.
Dual-licensed. Code: your choice of AGPL-3.0-only (free — but your derivative work, including SaaS, must be open-sourced too) or a paid FlowGT commercial licence for closed-source use. Documents: CC BY-NC-ND 4.0.
Reading, studying and citing are always free. Unauthorised commercial use will be pursued under New Zealand law. Details: LICENSING.md · NOTICE.md · commercial enquiries hello@flowgt.co.nz
- This is not the full product — the website, business logic and operational tooling are private.
- This is not a community project — no feature requests, no pull requests. It is published as verifiable reference, and that is its whole job.