CallForge AI Before sign-up Landing Onboarding Broker Dashboard Campaigns Calendar Calls Your week Leads Script Connections Wallet Team Admin QA queue Script review Cost centre Data requests Audit log Written CF-DOC-06
This top bar is review chrome, not product UI — it exists so you can walk every screen without hunting for links. Everything below it is the interface. All of it is live: forms validate, the script editor flags wording as you type, the recordings play, and the wallet arithmetic is real.
ScreenRouteWhat it demonstratesPage
Before sign-upLanding/public copy · sample call playslanding.html
Onboarding/welcome5 steps · validation · lead uploadwizard.html
BrokerDashboard/next meeting · needs-action · funnelportal.html
Campaigns/campaignsactive · paused · in-review · budgetportal.html
Calendar/calendarpending-YES · busy · now-lineportal.html
Calls/callslive wall · recording · transcriptportal.html
Your week/weekprep sheet · brief · verificationportal.html
Leads/leadsupload · consent source · quarantineportal.html
Script/campaigns/:id/scriptlocked blocks · lint · submitportal.html
Connections/settings/connectionstoken health · DNC sourcesportal.html
Wallet/walletVAT maths · top-up · ledgerportal.html
Team/settings/teamseats · roles · invitationsportal.html
Reports/reportsfunnel · per-campaign · export · scheduled emailnot built yet
Inbox/inboxunread · bulk-select · filtersnot built yet
Support/supportticket form · ticket list · dispute trackernot built yet
AdminQA queue/admin/qaage/SLA · decision · reject reasonadmin.html
Script review/admin/scriptsapprove · request changes · rejectadmin.html
Cost centre/admin/costsper-minute cost · marginadmin.html
Data requests/admin/dsarexport · erase · POPIA s23/s24admin.html
Audit log/admin/auditappend-only · actor · filtersadmin.html
Ops overview/adminseverity/SLA queue · live call wallnot built yet
Brokers/admin/brokersper-brokerage rates and marginsnot built yet
Pricing/admin/pricingper-client rate · free appointmentsnot built yet
WrittenCF-DOC-06design & build responsedocument.html

Screens marked not built yet are in your 06_Mockups_CallForge.html and are not in this prototype. They are listed so the gap is visible rather than implied.

CallForge AI — CF-DOC-06 Design & Build Response
CallForge AI

AI Outbound Appointment Engine for South African Insurance Brokers

Design & Build Response

What was built against the specification, the reasoning behind the wording it carries, what is still open, and what is needed to deploy

CF-DOC-06·Version 2.0·12 August 2026·Confidential Prepared for: J. Schoeman (BM Investments)·Owner: G. White (GhostAI) Supersedes Version 1.0 of 11 August 2026·Revision log at §11

What this document is

Your developer pack specified the product. This document reports back against it: what exists today, what does not yet exist, the reasoning behind the choices that were made along the way, and what is required before anything can be deployed to a real broker.

It follows the same convention as the rest of the pack and is numbered into it as CF-DOC-06. The direction is simply reversed — your documents were prepared for the development team; this one is prepared for you.

What changed in this version

Version 1.0 reported the state of the build. It was accurate but thin in one respect: it showed you what had been decided without showing you why, and a design you are being asked to freeze cannot be assessed on its appearance alone. Approving a screen means approving the reasoning underneath it, and that reasoning was largely undocumented.

Version 2.0 therefore adds four appendices. Appendix A takes the call script line by line and gives the legal or commercial reason for each phrase — including the phrases that are locked and cannot be edited by a broker. Appendix B does the same for the broker-facing copy. Appendix C documents the compliance lint rule by rule, with the reasoning for each rule’s severity. Appendix D is a decision register showing what each open decision blocks and what it costs to defer.

The ten original sections are unchanged in numbering, so any reference already made to “§6.2” or “§9” remains valid. Their content has been deepened, and four substantive changes have been made to Version 1.0 — three corrections and one new finding. They are listed at §11 rather than made silently. One of them withdraws a claim Version 1.0 made about your pack, and is set out at §6 as well as in the log.

On the screenshots in this document

The screens shown here are interactive prototypes, printed as stills. The stills carry the layout and the content, but not the behaviour. Form validation, the compliance lint that flags non-compliant script wording as it is typed, the keyboard-driven review queues, the live wallet arithmetic and the animated call in progress only exist when the prototype is opened. Each figure carries its live link. If you are reading this on paper, the links are printed alongside them.

Every link in this document is private and requires access. They are not public URLs and will not resolve for anyone outside this project.

A note on sourcing

Every factual claim in this document about what the system does is drawn from the system itself rather than from intention. Where a claim rests on a specific piece of the build, the file is cited — for example, the three-attempt retry limit at §6.3 is db/migrations/0004_spec_gaps.sql, and the wording rules in Appendix C are apps/api/src/modules/scripts/script-lint.ts. This matters because the difference between “the system prevents that” and “we intended the system to prevent that” is the difference between a defensible position and an expensive surprise.

Against the success definition

CF-DOC-01 §1 sets a single test for whether this product works:

“A broker logs in on Monday, sees five verified appointments in their calendar for the week, listens to the recordings, and walks into the meetings prepared.”

CF-DOC-01 §1 — Definition of success

That sentence was treated as the design brief rather than an aspiration, and it drove a screen of its own. “Your week” is the Monday prep sheet: the first thing a broker sees when they log in at the start of the week, built to be read in the order that sentence implies.

Why the brief sits above the recording

The sequencing is a deliberate decision and worth defending, because the obvious alternative — leading with the audio, which is the more impressive artefact — is worse.

The brief comes first: who the person is, what they hold now, what they said they wanted, what the AI committed to on the call. The recording sits underneath it. A broker about to walk into a meeting needs the summary, and reaches for the audio only when a specific detail is worth checking. Put the player first and you force them to listen to six minutes to recover thirty seconds of substance — which, on a Monday with five appointments, is half an hour spent to learn what a paragraph would have told them.

The recording is not decoration, though, and it is not buried. It is the evidence behind the brief, and its presence is what makes the brief trustworthy: a summary with the source attached can be checked, and a summary that cannot be checked is just an assertion. The design gives the broker the fast path by default and the slow path on demand.

Why “verified” is a claim with evidence, not a badge

Every appointment carries its verification alongside it — how the appointment was confirmed, when, and by what means. This is the product’s central claim and it is the one most easily hollowed out, so it is worth being precise about what it means.

“Verified” is not a status the system awards itself for having placed a call. It means the appointment was confirmed twice: once on the call, in the client’s own words on a recording that is retained, and once by SMS, where the client replied to a message that named the broker, the date and the time. Both artefacts are stored and both are shown. The screen displays the evidence rather than asserting the conclusion.

That was a deliberate response to the pack’s emphasis on brokers not wasting mornings on appointments that were never real, and it is also what makes the commercial model defensible: a broker pays per verified appointment, so “verified” is the definition of a billable event. A billing trigger that the platform can award itself without evidence is a dispute waiting to happen. Appendix B.3 covers the wording of this claim in the public copy, where it has to survive contact with a sceptical reader.

The screen answers your success test as written. What it cannot yet do is answer it with a real broker’s real appointments, because the portal that would serve it is not built — see §4.

CallForge AI 'Your week' screen: a Monday prep sheet listing the week's verified appointments, each with a written brief above its call recording.
Figure 1“Your week” — the Monday prep sheet. The week’s verified appointments in the order a broker uses them: the brief first, the recording underneath, and the verification evidence attached to each appointment. Answers the success definition in CF-DOC-01 §1 directly. Interactive version: https://claude.ai/code/artifact/82052755-30fe-48cf-96f0-2e7458b8bb74

The three-month diary in §3.5 is the same information at a different altitude: the week answers “what am I doing now”, the diary answers “is the pipeline actually filling”. Both were needed; neither substitutes for the other.

The screens

Seven screens were designed and built as prototypes. Each is shown below with what it is, the specification area it answers, and the reasoning behind its structure. They share one design language, one palette and one set of components, so they read as a single product rather than seven pages.

Public landing page

The marketing face of the product — the page a broker reaches before they have an account. It carries the approved wording from CF-DOC-05 verbatim rather than paraphrased, so the claims made in public are the claims that were signed off, and the positioning, the objection handling and the compliance language are the ones you approved.

Structurally it answers the question a sceptical broker actually asks, which is not “what is AI” but “what lands in my diary and how do I know it is real”. The verification story is therefore load-bearing on this page rather than a footnote.

Two of your own copy decisions do a lot of work here and are analysed in Appendix B: the headline sells the outcome rather than the technology, and the pricing language commits to paying for verified appointments only. Both are defensible under the Consumer Protection Act’s rules on marketing claims precisely because the QA gate makes them literally true rather than aspirational.

CallForge AI public landing page: the hero positioning alongside a worked example of a call — the AI disclosure, the qualifying exchange, the SMS confirmation and the resulting booked Teams appointment.
Figure 2Public landing page. The marketing face of the product, carrying CF-DOC-05’s approved wording verbatim. Answers the positioning, claims and public compliance language specified in the copy pack. Wording rationale at Appendix B. Interactive version: https://claude.ai/code/artifact/e587efb0-d7f9-4410-961a-edb8c7d4a3ca

Onboarding wizard

This screen exists to satisfy the first acceptance criterion in CF-DOC-01 §17: a broker registers, connects a calendar, tops up their wallet, builds a campaign and gets a script approved — unaided. No support call, no walkthrough, no hand-holding.

The wizard is therefore built as a single guided path with the state visible at every step, validation at the point of entry rather than on submit, and a cost estimate that updates as the campaign is defined so the broker understands what they are committing to before they commit.

The script step includes the compliance lint: prohibited wording is flagged as it is typed, with the rule that was broken named, so a broker learns the constraint rather than being rejected by a reviewer later. The lint is advisory rather than blocking for advice-like phrasing, and that is a deliberate design decision with a real argument behind it — Appendix C.4 sets it out. In short: a hard gate trains brokers to phrase around the wordlist rather than to write compliant copy, and it teaches the human reviewer to stop reading. Only a missing or tampered mandatory disclosure blocks submission outright.

One structural point that is invisible on paper: the mandatory disclosures are not lint rules at all. They live in locked blocks outside the editable body, so they cannot be edited away in the first place. The lint checks them as a tamper detector, not as the primary control. Appendix A explains what is in those blocks and why each clause is there.

This is the screen that most needs to be opened rather than read. On paper it is a form; in use it is the acceptance criterion.

CallForge AI onboarding wizard, showing the guided steps a broker completes to register, connect a calendar, top up and build a campaign.
Figure 3Onboarding wizard. Registration, calendar connection, wallet top-up, campaign build and script approval in one guided path. Answers the first acceptance criterion in CF-DOC-01 §17 — a broker completes this unaided. The compliance lint and step validation only run in the live version. Interactive version: https://claude.ai/code/artifact/1cadfa5f-e4e8-46ba-8551-77c4e4ebd681

Broker dashboard

The operational home screen: campaign state, wallet balance and burn, call outcomes, and the appointments that resulted. It answers the pack’s requirement that a broker can see at a glance whether the engine is working and what it is costing, without assembling that picture from four different screens.

The design bias here is towards outcomes over activity. Call volume is present but subordinate; appointments booked, appointments verified and cost per appointment are the figures given prominence, because those are the numbers a broker renews on. A dashboard that leads with dials placed would be flattering the platform rather than informing the customer — and under a pay-per-appointment model, dials are precisely the thing the broker is not paying for.

CallForge AI broker dashboard, showing campaign state, wallet balance, call outcomes and resulting appointments.
Figure 4Broker dashboard. Campaign state, wallet balance and burn, call outcomes and appointments booked. Answers the pack’s requirement that a broker can see at a glance whether the engine is working and what it is costing. Interactive version: https://claude.ai/code/artifact/9f90e403-aee5-4f78-b764-b92ff775d8fa

Your week

The Monday prep sheet described in §2. Briefs first, recordings underneath, verification attached to each appointment. This is the screen the success definition asks for, and it is deliberately the plainest screen in the product — it is read at speed, often on a phone, frequently in a car park before a meeting. Visual restraint here is a functional requirement, not a stylistic preference.

The figure for this screen appears in §2, where it answers the success test directly.

Three-month diary

The pipeline view. Where “Your week” is immediate, the diary is the horizon: appointments across a rolling quarter, so a broker can see density, gaps and whether the campaign is producing a pipeline or a spike. It answers the pack’s scheduling and capacity requirements — a broker cannot be booked into a week they cannot service, and the diary is where that becomes visible before it becomes a problem.

The quarter horizon is not arbitrary. It is long enough to show whether a campaign is sustaining a pipeline rather than front-loading it, and short enough that every appointment shown is one the broker can still prepare for or move.

CallForge AI three-month diary, showing appointments distributed across a rolling quarter.
Figure 5Three-month diary. The pipeline at a quarter’s horizon — density, gaps and whether the campaign is producing a pipeline or a spike. Answers the scheduling and capacity requirements in the pack. Interactive version: https://claude.ai/code/artifact/89b54676-867f-48bc-8477-74e3b50751fa

Admin console

The operator’s side of the product, and the largest single screen. It carries the QA review queue, script review and approval, the cost centre, data-subject requests and the audit log.

Three parts of it are worth drawing out, because each answers a specific obligation rather than a convenience.

The QA review queue is keyboard-driven by design. A reviewer working through a queue of calls should never need the mouse, because the volume is the whole difficulty: every appointment must be reviewed before it is billed, so review throughput is the constraint on the business model. A queue that takes six seconds per item instead of two does not merely annoy the reviewer — it sets the ceiling on how many appointments can be sold in a day.

Data-subject requests are a first-class screen rather than a mailbox, because POPIA gives data subjects rights on a clock. A request that sits unlogged in someone’s inbox is a missed deadline that becomes a reportable failure, and “we did action it, we just cannot show you when” is not a defence. The screen exists so the clock is visible and the response is recorded.

The audit log exists because every claim this product makes about consent, verification and approval has to be provable after the fact, to a regulator, without reconstructing it from application logs. Appointment status changes are written by a database trigger rather than by application code (§8.1), which means no code path can change a status without leaving evidence — including a code path written in a hurry two years from now.

CallForge AI admin console, showing the QA review queue, script review, cost centre, data-subject requests and audit log.
Figure 6Admin console. QA review queue, script review and approval, cost centre, data-subject requests and audit log. Answers the operational, QA and POPIA-accountability requirements of the pack. The review queue is keyboard-driven in the live version. Interactive version: https://claude.ai/code/artifact/295b0379-76fb-41d9-a983-c0aa128b79f0

The portal

All of the above assembled behind one navigation, so the product can be walked end to end as a broker would actually experience it, rather than as seven separate pages. If only one link is opened, this is the one — it contains the others.

CallForge AI portal, showing all broker and admin screens assembled behind a single navigation.
Figure 7The portal — all screens, one navigation. Every screen above assembled as a broker would experience it. If only one link is opened, this is the one. Interactive version: https://claude.ai/code/artifact/74668fe8-d663-4aea-9be9-d0d019dcc28e

Supporting documents

All links in this document are private and require access.

What is built, and what is not

The honest position, component by component. Where something is not built, it is stated as not built. The column that matters most is the third one, because “built” without a statement of what was verified is a claim rather than a report.

Build state as at 12 August 2026
ComponentStateDetail and basis for the claim
API and business logic Built and tested Wallet, campaigns, leads, scheduling, the AI’s tools, appointments, QA, notifications and admin. 55 tests passing against live PostgreSQL — not mocks, the real database with the real constraints active, so a test that violates a money or consent rule fails on the constraint rather than on a stub that was written to agree with it.
Database Built and verified Five migrations. Tenant isolation, money rules and consent rules are enforced by the database itself rather than by application code. See §8 for why that distinction matters commercially.
Infrastructure Written, not applied Terraform for AWS Cape Town, 12 files. It has not been run against a real AWS account, so it is unproven in the way that only actually applying it can prove. Blocked on D3 and A1, not on engineering effort.
Portal screens Designed, not built The prototypes in §3 are the design. The Next.js application behind them is a placeholder of four files. This is the largest single remaining piece of work in the project.
Voice agent Contract only The API the voice agent calls is built and tested. The calling pipeline itself is currently configuration rather than implementation.
Telephony transport New scope SIP signalling and the RTP audio bridge, consequent on the move to Utility Connect. See the note below — this did not exist in the original scope.
Accounts and domain Not started No domain registered, no production accounts opened. Several long-lead items depend on this — see §10.

The Utility Connect change is added scope, not a swap

Moving the telephony from Twilio to Utility Connect changes the shape of the work rather than merely the supplier. Twilio provides a managed media layer; a SIP trunk does not. That means SIP signalling and an RTP audio bridge now have to be built — call setup, teardown, codec negotiation, and a real-time audio path between the trunk and the AI in both directions, with latency tight enough that the conversation does not feel broken.

This is worth naming plainly because it reads on a plan as a line-item substitution and is not one. The business logic was unaffected (§8.2 explains why), but the telephony layer is new work that did not exist in the original scope. It is listed as its own row in the table above for that reason: burying it inside “voice agent” would understate it.

The five decisions only you can make

Five decisions are outstanding. None of them are technical, none can be answered by the development side, and each blocks work that cannot sensibly start without it. They are listed in the order they unblock the most. Appendix D sets out the same five as a register, with what each one blocks and what deferring it costs.

B1 Price per appointment

What a broker pays for a verified appointment. This is the commercial foundation of the product and everything downstream of it is currently provisional.

Nobody else can set this. It is a judgement about what the South African broker market will bear against what an appointment is worth to a broker who closes on it — a commercial position, not a calculation, and yours to take.

One input to it is now known that was not known when the pack was written: the NCC cleansing fee at §6.1 is a recurring cost per record per month, and it lands on the platform whether or not a record is ever called. That is a floor under the price, and §6.1 sets out the choice about who carries it.

Blocks — the wizard’s cost estimate, the wallet and top-up screens, the pricing section of the landing page, the Terms of Service, and the unit economics that determine whether the compliance costs in §6.1 are absorbed or passed on.

D1 Where platform leads come from, and under what consent wording

The source of leads that CallForge supplies itself, as distinct from leads a broker brings, and the exact wording under which those people consented to being called.

This is a decision about supplier relationships and about what you are prepared to warrant to brokers regarding lead provenance — commercial and contractual ground, not engineering. §6.3 has sharpened it considerably: it is now the decision that determines the retry policy, and with it whether the calling model is legally defensible at all.

Note that the exact wording matters as much as the source, and not only as a legal formality. The script has to be able to answer “how did you get my number?” with a specific, truthful sentence — that sentence is a field in the system, and Appendix A.7 explains why it is populated per lead source rather than written once.

Blocks — the consent model in the database, the Privacy Policy’s lawful-basis section, the broker contract’s warranties, the “how did you get my number” script branch, and the entire question of whether outbound is cold or warm.

A1 Register the domain

The production domain the product will live on. Small in itself, disproportionate in what it holds up.

It is a branding decision and a purchase, both of which are yours. It is listed here because it is the cheapest item on this page and one of the most blocking.

Blocks — Google’s OAuth app review (2–6 weeks, and it cannot begin without a verified domain), production email deliverability, TLS certificates, the published legal documents, and every account that needs an address at the company’s own domain rather than a personal one.

D3 Whose accounts, and billed where

Which legal entity holds the AWS, telephony, AI provider and payment accounts, and which entity is billed.

This is an ownership and liability question. It determines who is contractually the responsible party to suppliers, who is the operator under POPIA, and who carries the accounts if the working relationship changes. It cannot be decided by whoever happens to open the account first, and it is materially harder to unwind later than to set correctly now.

Blocks — opening any production account, applying the Terraform in §4, the NCC registration in §6.1, and the responsible-party identification that both legal documents require.

D2 Who the pilot brokers are

The named brokerages the first deployment targets.

This is a relationship decision and rests on who you can actually put in the room. It also has a real design consequence: pilot brokers with existing customer books make the warm-outbound model in §6.2 immediately viable, while pilot brokers without them do not.

Blocks — which parts of the portal get built first, the data the system is seeded and tested with, and the first genuine test of the design against a real user with real leads (§9).

On the number in the screens

The prototypes display R650 per appointment. That figure is a placeholder, used purely so the screens have a number in them and the arithmetic visibly works. It is not a recommendation, not a calculation, and carries no analysis behind it. It changes the moment B1 lands.

It is stated here rather than left to be discovered because a plausible-looking number in a mockup has a way of becoming a real one by default. This one should not.

The South African compliance position

Two compliance findings emerged during the build. Both are material and one bears directly on the commercial model rather than merely on paperwork. A third item follows from them: a place where the system as specified and built conflicts with the legal reading, set out at §6.3.

This section is corrected in Version 2.0

Version 1.0 presented both findings under the heading “South African law changed after the pack was written”. That was wrong on the dates and is withdrawn.

Your pack is dated August 2026. The NCC regulations at §6.1 came into force 15 April 2026 — nearly four months before it. And the s69 position at §6.2 is not a change at all: CF-DOC-01 §13 already cites it, naming the Information Regulator’s Guidance Note of December 2024 and stating that the platform is built consent-first as a result.

So neither finding post-dates your pack. §6.1 is an obligation the pack does not mention; §6.2 is one the pack identified correctly, and where the build has since revealed a conflict you could not have anticipated. The corrected framing is at §11, R4.

Direct marketers must register with the National Consumer Commission

The Consumer Protection Act Amendment Regulations came into force on 15 April 2026, with no transitional period. There was no grace window and no phase-in; the obligations applied on the day.

This is the one finding genuinely absent from the pack — the National Consumer Commission, the registration requirement and the cleansing fee are not mentioned in any of CF-DOC-00 through CF-DOC-05. It is raised here as a gap rather than as news, and the practical consequence is the same either way: the obligation has been live since April and is not waiting for launch.

Three obligations follow for any direct marketer:

The third point is the one with commercial teeth. The fee scales with database size and recurs every month regardless of whether a record is ever called. At 100,000 records the cleansing cost is in the region of R12,000 per month. That is a standing cost of operating, and it belongs in the price before the price is set — which is a direct input into decision B1.

There is a second-order effect worth naming: because the fee is charged per record held rather than per record called, holding a large unworked lead database is now expensive by itself. A strategy of acquiring volume and working through it slowly is penalised monthly. This argues for smaller, better-qualified lead sets, which happens to align with the direction §6.2 pushes for independent reasons.

The contract question underneath it

Does CallForge absorb the cleansing cost, or does the broker carry it? This is not a detail that resolves itself. If CallForge absorbs it, the cost sits against margin and scales with the platform’s own lead database. If the broker carries it, it has to appear in the broker contract, be explained during onboarding, and be visible in the portal — which is a design change, not just a commercial one. Either answer is workable; leaving it unanswered until after launch is not.

Marketing calls are opt-in, not opt-out — as your pack already recognised

This is not a new finding, and Version 1.0 was wrong to present it as one. Your own specification states the position precisely:

“The Information Regulator’s Guidance Note on Direct Marketing (December 2024) treats outbound marketing calls as electronic communication requiring prior consent — the platform is built consent-first: no provable consent, no dial.”

CF-DOC-01 §13 — Compliance

CF-DOC-04’s risk register says the same thing in the mitigation column: “consent-first design already assumes the strict reading; monitor Information Regulator; kill-switch per campaign.” The instruction was correct and the build followed it — the consent gate at §8.1 is that instruction expressed in the database.

What is worth restating is the consequence, because it is sharper than “get consent first” suggests. A telephone call is an electronic communication under POPIA s69. Under that reading, approaching a person who is not already a customer is constrained to one approach, and that approach may only be made to request consent. Consent must be read aloud on the call and the recording retained as the record of it. There is no second attempt if consent is not given.

That last sentence is where the pack and the build diverge, and it is the genuinely new material in this section — see §6.3.

This puts pure cold outbound under real pressure in South Africa

Stated plainly: a model built on repeatedly calling strangers to book appointments is difficult to defend under the current reading of s69. One approach, consent-only, with the consent recorded, is not a volume outbound model — it is a permission-gathering exercise that happens to use the phone.

The defensible shape is warm outbound. Two routes qualify:

  • Calling a broker’s existing customers under the s69(3) similar-products exception — an established relationship, a related product, and a working opt-out.
  • Calling leads that carry recorded consent — where the consent to be contacted was captured at source and can be produced on demand.

This is a commercial decision for you, not a compliance detail to be handled downstream. It determines what CallForge sells, who it sells to, and what a broker has to bring to the table before the engine can run for them. A brokerage with a book of existing customers is a very different prospect to one buying cold volume, and the product positioning follows from which one you are building for.

Consistent with that, your copy in CF-DOC-05 already assumes the warmer model. The homepage says CallForge “phones consented prospects”, the proof strip says “consented data only”, and one of your three tagline options is “Appointments, not cold calls.” The approved public wording needs no revision — which is not luck but the same consent-first reading applied to the marketing, and is analysed in Appendix B.1.

Where the built system conflicts with this reading

This is the genuinely new material in this section, and the most actionable. It was not stated in Version 1.0. Unlike §6.1 and §6.2 it is not a question of what the law says — it is a conflict between two parts of your own pack that only became visible once both were built.

CF-DOC-01 §6.4 specifies a retry pattern, and it is built as specified: a lead that does not answer or asks to be called back is retried, with attempts spread across different days and different parts of the calling window. The platform default is three attempts per lead per campaign (db/migrations/0004_spec_gaps.sql), and the objection-handling branch in your own script at CF-DOC-05 §6.1 offers to “call back tomorrow morning or afternoon”.

Against the one-approach reading of s69, that is three approaches where the law appears to permit one, for any person who is not already a customer of the brokerage.

The conflict is not fatal, and it does not require abandoning the retry pattern. It requires the retry limit to become conditional on the lawful basis of the lead rather than a single platform-wide default:

Mechanically this is a small change: the attempt cap moves from one platform-wide number to a value resolved per lead from its consent record, and the scheduler already reads the cap from configuration rather than hard-coding it. It is called out here because it is exactly the kind of item that is cheap now and expensive after launch — and because it is a case where the system does what your specification asked for, and the specification predates the guidance. It is flagged, not fixed, because the correct values depend on D1.

The immediate effect on §5 is that D1 moves from important to blocking. Where platform leads come from, and the exact wording under which those people consented, is now the question that determines whether the calling model stands up. It cannot be settled after launch.

Recommendation: a POPIA-literate attorney should review the calling flow before launch — specifically the consent script, the s69(3) reliance where existing customers are called, the retry policy set out above, the retention of consent recordings, and the opt-out mechanism. This is a review of the flow itself, not only of the published documents.

Legal documents

A Privacy Policy and Terms of Service exist as attorney-ready drafts. They are drafts in a specific sense: the structure is correct, the factual content is accurate because it was drawn from the actual system rather than from a template, and every point that depends on an unmade decision is marked as an explicit blank rather than filled with a plausible guess.

32 attorney notes are raised across the two documents, each flagging a point that needs legal judgement rather than drafting.

They cannot be finalised yet, for two reasons. The first is §5: several clauses depend directly on the five open decisions, and cannot be written until those land. The second is more important — a published policy binds whoever publishes it. A Privacy Policy is a statement of fact about what a system does with personal information, and publishing one that overstates or understates the position creates liability rather than covering it. These need an attorney’s review before they go live, not after.

Special personal information: the race field

This corrects Version 1.0

Version 1.0 stated that the race column is “being held without being used for anything the product does”. That understated the controls that are actually in place, and the corrected position below is materially stronger. The recommendation is unchanged; the reasoning behind it is not.

The database carries a race field on the lead record. Under POPIA s26 that is special personal information, which requires a higher lawful basis to process and attracts materially greater obligations and exposure.

Three controls govern it, and all three are built:

So the position is better than Version 1.0 described: the field is consent-gated, excluded from the broker-facing product, and audited. Your own pack anticipated the risk and the build implements what it asked for.

The recommendation nonetheless stands: consider removing the column entirely. The argument is no longer “it is unused and therefore pointless” but something narrower and more practical — the controls above are correct, but they are controls that must go on being correct through every future change, migration and query. Special personal information that delivers no identified product benefit is a permanent compliance surface maintained for no return. Removing it retires that surface completely rather than defending it indefinitely.

If there is a business reason to retain it that has not surfaced on the development side — a reporting obligation, a carrier requirement, a targeting use you intend later — that reason needs to be stated, so the lawful basis can be documented properly and the field can be justified rather than merely defended. This is a question for you and the attorney together; it is not a decision the development side should take alone in either direction.

Technology, briefly

The full reasoning is its own document — Technology stack, and why. In summary: a NestJS/TypeScript API, PostgreSQL with row-level security, a Next.js portal, a Python voice agent, running on AWS Cape Town, provisioned by Terraform.

Two architectural arguments are worth making here rather than leaving to the appendix, because both are commercial rather than technical.

The database enforces the rules, not the application code

Three rules in this system would end the business if broken. Each is enforced one layer below where bugs happen. Your own START_HERE document names two of them as non-negotiables, and the build takes them literally.

The commercial framing is straightforward: these are the failures that would be existential rather than embarrassing, so they are placed where application bugs cannot reach them. It costs more to build this way. It costs considerably less than a cross-tenant data leak reported to the Information Regulator, or a billing dispute that cannot be answered from the record.

There is a second benefit that matters for what comes next. The portal is the largest remaining piece of work (§4), and it will be built at pace. Rules that live in the database do not weaken because a screen was built quickly.

Every external service sits behind an interface with a mock

Telephony, AI providers, payments, email — each is accessed through an interface, with a mock implementation used in testing. This is why the 55 tests in §4 can run against a live database without placing a single real call or charging a single real card.

It also has a concrete payoff already realised: swapping Twilio for Utility Connect touched no business logic. The campaign rules, wallet arithmetic, consent checks and scheduling did not change, because none of them ever knew which supplier was carrying the call. The new work is confined to the telephony layer — which, per §4, is real work, but it is contained rather than spread through the system.

This is worth registering as evidence rather than as a design preference. The supplier change was not anticipated when the interfaces were drawn, and it still cost nothing in the core of the system. That is the return on the extra cost noted above, collected once already, before launch.

What “frozen” can and cannot mean

You have asked that the design be perfected now and held unchanged until deployment. The intent behind that is right — a design that keeps moving never ships, and a build that chases a moving target wastes effort. It is worth being precise about what can be locked and what genuinely cannot, so that “frozen” means the same thing on both sides.

What can be frozen, and should be

That is the majority of the design, and it is genuinely stable. It can be signed off today. Version 2.0’s appendices exist partly to make that sign-off meaningful: approving wording whose reasoning is documented is a decision, where approving wording on sight is a hope.

What cannot be frozen, honestly

Anything downstream of the five open decisions. The price alone is instructive: B1 touches the wizard’s cost estimate, the wallet and top-up screens, the pricing section of the landing page and a clause in the Terms. Freezing screens that contain a placeholder number does not freeze them — it defers the change to a less convenient moment.

The legal position, which is still settling. The Information Regulator’s guidance on s69 dates from December 2024, but how strictly it is applied to voice calls is being worked out now, and the NCC regime at §6.1 has been in force only since April. §6.3 is a live example of what that produces: a retry pattern built exactly to CF-DOC-01 §6.4 needs a condition on it that follows from CF-DOC-01 §13 — two parts of the same pack, consistent on their own and in tension once built. If the consent model tightens further, the screens that carry consent move with it. That is outside anyone’s control here.

Whatever the first pilot broker surfaces. No amount of review substitutes for one real user with their own leads, their own book and their own way of working. They will find something — a step that reads clearly to us and not to them, a field that matters more than we assumed, a workflow that does not match how they actually run their week. That is the point of a pilot, and a design that cannot absorb it was frozen too early.

The useful way to hold this

The mockups are the specification, not the deliverable. Approving them means approving the decisions they encode — the structure, the flows, the visual system, the way verification is presented, the compliance behaviour. It does not mean committing that no pixel moves between now and launch.

The route to actual stability is §5. The design is not moving because it is unsettled; it is moving because five inputs to it are still open. Settle those five decisions and the design stops moving — not by policy, but because there is nothing left for it to move in response to.

What is needed to proceed

Four things, in the order they unblock the most.

The five decisions

B1, D1, A1, D3 and D2, per §5 and Appendix D. These are the constraint on nearly everything else in this list. D1 is now the most urgent of them for the reasons given in §6.2 and §6.3 — it determines whether the calling model is cold or warm, it sets the retry policy, and that determines what the product is.

Start the long-lead items now

Three items take calendar time that cannot be compressed and should be started in parallel with everything else:

An attorney briefed

A POPIA-literate attorney, briefed on the calling flow as well as the documents. The scope is: the s69 position and whether the intended model relies on s69(3) or on recorded consent; the retry policy at §6.3; the consent script and how it is captured on the call; the retention of consent recordings; the race column at §7.1; and the 32 notes raised across the two drafts. Appendix A is written to be handed to them directly — it sets out each clause of the script and the reason it is worded as it is, which is the form a review is cheapest to run against.

This should happen before launch, not at it.

A first pilot broker chosen

The build has to target someone specific. Which broker is chosen changes what gets built first — and per §6.2, whether that broker has an existing customer book materially changes which calling model the first deployment can actually use. This is D2, and it is the decision that turns a specification into a plan.

Where this leaves things

The API, the business logic and the database are built and tested. The product is fully designed, and as of this version the reasoning behind the design is documented rather than implicit. The infrastructure is written. What stands between that and a broker logging in on a Monday is the portal build, the telephony layer, and five decisions that only you can make — and the decisions are the shorter pole. Everything in §10 that is not blocked on a decision can start immediately.

Revision log

This document is numbered into your pack and will be revised as decisions land. Changes are recorded here rather than made silently, so that a version you approved can be distinguished from a version you have not yet read.

Version history
VersionDateChange
1.0 11 Aug 2026 First issue. Ten sections reporting build state, the five open decisions, the two legal findings, and the position on freezing the design.
2.0 12 Aug 2026 Adds the reasoning behind the product’s wording as Appendices A–C, and a decision register as Appendix D. Deepens all ten sections and adds this log as §11. Four substantive changes, listed below.

Substantive changes in Version 2.0

Three corrections and one new finding. They are called out individually because each changes something you might act on.

R1 Correction — the race field is better controlled than stated (§7.1)

Version 1.0 said the column was “held without being used for anything the product does”. In fact three controls are built: the value is discarded at import unless the consent record covers special personal information, the field is excluded from broker-facing campaign targeting on the instruction in your own CF-DOC-01 §4.2, and admin-side use is gated and audit-logged.

The recommendation to consider removing the column is unchanged, but the argument for it is different and narrower: not that the field is unguarded, but that guarding it correctly forever has an ongoing cost and no identified return.

R2 New finding — the retry pattern conflicts with the s69 reading (§6.3)

Not raised in Version 1.0. The built system retries a lead up to three times per campaign, exactly as CF-DOC-01 §6.4 specifies. Under the one-approach reading of s69 at §6.2, that is three approaches where one may be permitted for anyone who is not already a customer.

The fix is to make the retry limit conditional on the lead’s lawful basis rather than a single platform default. It is flagged rather than implemented because the correct values depend on D1. This is the clearest example of why D1 is now blocking.

R3 Clarification — telephony transport is its own line (§4)

The SIP and RTP work consequent on the Utility Connect change now appears as its own row in the build-state table rather than inside “voice agent”. Version 1.0 described it accurately in prose but the table understated it, and a table is what gets read.

R4 Correction — §6 was wrongly framed as law changing after the pack

Version 1.0 titled §6 “South African law changed after the pack was written” and opened it by saying both findings post-dated the pack. Neither claim survives the dates, and both are withdrawn.

Your pack is dated August 2026. The NCC regulations came into force 15 April 2026, roughly four months earlier. And the s69 opt-in position is cited in your own CF-DOC-01 §13, which names the Information Regulator’s Guidance Note of December 2024 and states that the platform is built consent-first because of it — a position CF-DOC-04’s risk register repeats. The guidance predates the pack by some twenty months.

The corrected position: §6.1 is an obligation the pack does not mention anywhere, raised as a gap. §6.2 is a position the pack identified correctly and the build implemented. Only §6.3 — the retry conflict — is genuinely new, and it arises from two parts of your pack being in tension once built, not from any change in the law.

This matters beyond accuracy. The original framing implied an oversight on your side where there was none, and it obscured the one finding that does need your attention.

Everything else in Versions 1.0 and 2.0 agrees. Section numbering is unchanged, so references made against Version 1.0 remain valid.

Appendices

The reasoning behind the product’s wording, the compliance lint, and the open decisions. Appendix A is written to be handed to an attorney as-is.

Why the call script is worded as it is

This appendix takes the master call script at CF-DOC-05 §6.1 and gives the reason for each clause. It exists because the script is the highest-risk text in the product: it is read aloud to members of the public, hundreds of times a day, by an automated system, on behalf of a licensed financial services provider. Every sentence in it is either required, permitted, or a liability.

Three bodies of law bear on it. POPIA governs the personal information and the consent. The FAIS Act governs the boundary between qualifying a prospect and giving financial advice, which only a licensed adviser may do. The Consumer Protection Act governs the marketing claims and the right to be left alone. Where a clause serves one of these, it is named.

The locked opening, clause by clause

The opening block is locked: it sits outside the editable body of the script and a broker cannot change it. That is a structural control rather than a lint rule — the wording cannot be edited away, so the lint’s job is only to detect tampering, not to police intent (Appendix C.1).

Locking has a cost, and it is worth stating: it removes flexibility from the broker who knows their market best. It is justified because each of the four clauses below is a legal requirement rather than a stylistic choice, and a requirement that can be edited is not a requirement.

Clause 1 — recording disclosure disclosure.recording“…this call is recorded…”

Stated first, before anything else of substance is said, because the recording begins before the disclosure does. A person must know they are being recorded from the point at which the recording could matter to them.

It is also the load-bearing clause for the entire verification claim. The recording is what makes “verified” a fact rather than an assertion (§2.2), what evidences consent under §6.2, and what a QA reviewer assesses before the appointment is billed. If this disclosure fails, the recording is compromised, and if the recording is compromised the product has no product.

Rejected alternative — Disclosing the recording at the end of the call, which some scripts do to avoid an early drop-off. It would make every recording taken before that moment questionable, including the consent it is meant to evidence.

Clause 2 — AI disclosure disclosure.ai“…I’m an AI assistant calling on behalf of {brokerage}…”

Disclosed plainly, in the first breath, and not on request. Two reasons, and the second is the stronger one.

The compliance reason: a synthetic voice that a person believes to be human is a misrepresentation, and the Consumer Protection Act does not look kindly on misleading a consumer about who they are dealing with. The reputational reason: the disclosure will happen eventually — the person will guess, or ask, or be told by a colleague — and a disclosure that arrives late reads as a concealment that failed. Volunteering it costs a small number of immediate hang-ups. Concealing it costs the brokerage’s name.

Your own copy makes the same bet and states it more confidently than a compliance note would: CF-DOC-05 §2 answers “Will clients know it’s AI?” with “Yes — we disclose it, and it books better because it never has a bad day.”

Rejected alternative — “automated assistant” or “virtual assistant”, both of which are softer and both of which invite the follow-up question. The lint accepts them; the master script does not use them.

Clause 3 — the opt-out offer disclosure.optout_promise“You can say stop at any time and I’ll remove your details.”

Two commitments in one short sentence, and both are enforced by the system rather than by the AI’s good behaviour.

“At any time” means the opt-out is not confined to the end of the call or to a menu. The word “stop” is a recognised objection branch and terminates the call wherever it occurs.

“I’ll remove your details” is the stronger promise, and the reason the wording is not the weaker “I’ll note that”: the number is written to the do-not-call list, and the dialler cannot reach a number on that list because the query that selects who to call excludes it structurally (§8.1). The promise is kept by the database, not by a process.

Saying “remove your details” and merely flagging the record would be a false statement made on a recorded line, to a consumer, about their privacy rights. The wording was chosen to be strong, and the system was built to make it true.

Rejected alternative — “you may opt out at any time” — accurate, and legalistic in a way that invites suspicion. The script is spoken, and spoken registers should sound like a person.

Clause 4 — identification of the brokerage disclosure.identification“…on behalf of {brokerage}…” · “{broker_first_name}, a licensed adviser…”

The call is made on behalf of a named, licensed FSP, and the person is entitled to know which one before deciding whether to continue. An unidentified marketing call is the pattern of a scam call, and a consumer’s instinct to treat it as one is correct.

“A licensed adviser” does a second job: it sets up the FAIS boundary that the rest of the script depends on. The AI is explicitly not the adviser; it is arranging a conversation with one. Everything the AI is prevented from saying later (A.3) follows from this sentence being true and said early.

Why the AI qualifies but never advises

This is the FAIS boundary, and CF-DOC-01 §5.2 states it exactly: “the AI qualifies interest and books the appointment; only the licensed broker advises.” It is the single most consequential constraint on the script, because crossing it is not a marketing problem but an unlicensed-advice problem, and the exposure sits with the FSP whose name was given in Clause 4.

The practical difficulty is that the line is not intuitive. “Do you have life cover?” is a question. “You need more life cover” is advice. Between them sits a range of phrasings that feel conversational and are not permitted.

Permitted — qualifying“Do you currently have life cover in place — something that would settle your debts and look after your family if the unexpected happened?”

This establishes a fact about the person’s situation and their interest in discussing it. It recommends nothing, compares nothing, and asserts nothing about whether their current position is adequate.

The descriptive clause — “settle your debts and look after your family” — explains what the product category is for, which a person may genuinely not know. It stays on the right side of the line because it describes the category rather than the listener’s need for it.

Prohibited — advice fais.advice_verb“I’d recommend…” · “you should take out…” · “you’re paying too much” · “this policy performs better”

Each of these asserts a recommendation, a comparative merit claim, or a conclusion about the listener’s financial position. All three are advice under FAIS, and the AI is not licensed to give it.

“You’re paying too much” deserves particular attention because it is the most natural thing a salesperson says and it is squarely over the line: it is a conclusion about this person’s specific arrangements, reached without seeing them.

Rejected alternative — Allowing these where the broker “approves the wording”. A broker cannot license the AI to advise, because the licence attaches to the person, not to the script.

The reframe that keeps the value pitch legal“{broker_first_name} does a free, no-obligation review over a short Teams call — {he/she} checks whether you’re over- or under-covered and what that’s costing you.”

This is the most carefully built sentence in the script, and it is worth seeing what it does. It delivers the entire commercial pitch — you may be over-covered, you may be under-covered, it may be costing you — while attributing every judgement to the licensed human who will make it later.

The AI does not say the listener is over- or under-covered. It says the broker checks. The distinction sounds like a technicality in isolation and is the whole difference between marketing and unlicensed advice.

“Free, no-obligation” and “about twenty minutes” are there for a different reason: the two objections that kill an appointment are cost and time, and answering both before they are raised is what makes the booking rate work.

Why every objection has a scripted branch

CF-DOC-01 §5.2 requires objection handling, and the lint warns when a branch is missing (Appendix C.3). The reason is narrower than “good sales practice”. An AI without a scripted branch for an objection will improvise one, and an improvised answer to “how did you get my number?” is a POPIA statement made without supervision. The branches exist to remove the AI’s discretion at exactly the moments where discretion is dangerous.

The hard opt-out branch.opt_out“Done — you won’t hear from us again. Sorry to have disturbed you, and have a lovely day.”

No retention attempt, no “may I ask why”, no final offer. The call ends.

This is a legal boundary and not a customer-service preference: a marketing call that continues after a withdrawal of consent is the clearest possible breach, it is recorded, and the recording would be the complainant’s evidence. A single retention attempt would convert the product’s best compliance artefact into its worst.

“Sorry to have disturbed you” is deliberate. The person was called without asking to be, and the last thing they hear should acknowledge that.

Not interested — note the second sentence branch.not_interested“No problem at all, thanks for your time — should I take you off our list as well?”

“Not interested” is a refusal of the offer, which is not the same as a request never to be contacted. Treating the two as identical would either over-suppress records or, worse, under-suppress them by assuming the person will say “stop” if they mean it.

Asking the question resolves the ambiguity on the recording, where it can be evidenced later. It also happens to be courteous, which is why it does not sound like a compliance step when heard.

How did you get my number? branch.data_source“{consent_source_text} — and if you’d like, I’ll remove you right now.”

This is the branch with a variable in it, and the variable is the point. Under POPIA a person may ask where their information came from and is entitled to a truthful, specific answer — which differs per lead source and therefore cannot be a single sentence written once.

So {consent_source_text} is populated from the consent record attached to that individual lead. If the consent record cannot furnish a truthful sentence, the honest conclusion is that the lead should not have been called: this branch is where a weak lead source becomes audible, on a recording, to the person affected.

That is a direct dependency on D1. The decision about where platform leads come from is also the decision about what this sentence says, and it is one of the reasons D1 is now blocking (§6.2).

The offer to remove follows immediately in the same breath, because a person who asks this question is often a step away from asking to be removed, and making them ask for it separately is friction placed in front of a right.

Call me later branch.call_later“When suits you better — I can call back {tomorrow morning} or {afternoon}?”

Read this branch against §6.3. It presumes a second approach is available, which is true for an existing customer under the s69(3) exception and is doubtful for anyone else under the one-approach reading of s69.

The wording itself is fine. What needs to change is when the branch is permitted to fire: it should be conditional on the lead’s lawful basis rather than always available. This is the script-level face of the retry-limit finding at §6.3, and it resolves the same way — with D1.

Rejected alternative — Removing the branch entirely. That would be over-correction: for existing customers, a call-back request is an ordinary courtesy and refusing it would be strange.

Already covered branch.already_covered“That’s great — most people {broker_first_name} meets are covered; the review simply checks you’re not overpaying. Worth twenty minutes?”

The one branch where the wording is doing something commercially clever and legally careful at once. “Already covered” is not a refusal — it is often the most qualified prospect on the list, because they have demonstrably bought the category before.

It stays legal by the same reframe as the value pitch: the AI does not say they are overpaying. It says the review checks. “Most people {broker_first_name} meets are covered” is a statement about the broker’s own client base rather than a population statistic, which is why it does not trip the unsourced-generalisation rule at Appendix C.2 — a genuinely close call, and worth an attorney’s eye.

Why the confirmation is read back, and locked

The locked confirmation block“Just to confirm, {client_name} — {day} at {time}, a Microsoft Teams call about {product} with {broker_first_name} from {brokerage}. Is that right? … You’ll get an SMS with the Teams link now — please reply YES to it so we know you’ve got it.”

This block creates the billable event, which is why it is locked and why it names every particular back to the client: who, what, when, with whom, on what platform. A confirmation that omits a particular cannot evidence agreement to it.

“Is that right?” is the first of the two confirmations described at §2.2. It elicits an affirmative answer on the recording, in the client’s own voice, after the details have been read to them. The SMS reply is the second, in a different channel, which is what makes the pair meaningful — two confirmations on the same channel would prove only that the channel worked.

This is the mechanism behind the public claim “confirmed twice — on the call and again by SMS” (Appendix B.3), the QA reviewer’s evidence, and the answer to a broker who disputes a charge. It is the commercial core of the product expressed as three sentences of dialogue.

What the AI is not permitted to discuss at all

CF-DOC-05 §6 closes with a reviewer’s note that is easy to skim past and is doing important work: “Health-condition questions are not asked by the AI — they belong in the broker’s advice conversation.”

Health information is special personal information under POPIA s26, the same category as the race field discussed at §7.1, and it attracts the same elevated obligations. An AI that asks about health conditions on an outbound marketing call would be collecting special personal information from a person who has not consented to that collection, and recording it. The prohibition is absolute rather than a matter of phrasing.

The same note handles the discount claim: the seed script’s “exclusive 20% discount for being in good health” line may be used only where the carrier has that offer in writing. It fails on two counts otherwise — an unsubstantiated marketing claim under the CPA, and a health-status inference. The lint flags the percentage for manual check (Appendix C.2).

Why the broker-facing copy is worded as it is

The public copy at CF-DOC-05 is yours and was approved before the build began. It is carried into the landing page verbatim rather than paraphrased, and this appendix explains what each key phrase is doing — both because the reasoning is worth having on the record, and because two of these phrases turn out to be load-bearing legally as well as commercially.

The general observation is that the copy is more defensible than it needed to be. It was written to sell, and it happens to sit well within the Consumer Protection Act’s rules on marketing claims, because it promises things the system actually does. That is not automatic and it is worth not breaking later.

B.1 — The positioning“Stop cold calling. Start advising.” · “Appointments, not cold calls.” · “You advise. We dial.”

All three tagline options sell the broker’s outcome rather than the technology, which follows your brand voice note at CF-DOC-05 §1: “We sell time back and a full diary — not ‘AI’. The AI is the how, never the hero.”

They also do something you could not have planned for. Each of them positions the product against cold calling rather than as a way of doing more of it — and per §6.2, cold calling is precisely the model that South African law has made difficult since your pack was written. The copy needs no revision to survive the s69 reading, because it never promised cold volume in the first place.

“You advise. We dial.” additionally states the FAIS boundary of Appendix A.3 in four words, to the audience that most needs to understand it. If a tagline is still to be chosen, that is a point in its favour.

B.2 — The consent language“phones consented prospects in your area” · “POPIA-first — consented data only, instant opt-outs, recorded disclosures on every call”

“Consented” appears in the first sentence of the hero subhead, not in a footer. That was a positioning decision — it answers the broker’s unspoken question about whether this will embarrass them — and it has become a legal asset.

It is also a claim the system can substantiate: a lead without a consent record is unreachable by the dialler, structurally (§8.1). The word is doing work rather than decorating.

The obligation it creates runs the other way, though, and is worth naming: having said “consented data only” in public, the platform must not sell a lead list that cannot evidence consent. This is D1 again. The copy has already made a promise that D1 must be answered to keep.

B.3 — The verification claim“You only pay for appointments that are verified — never for dials, never for maybes.” · “Every appointment is confirmed twice — on the call and again by SMS.”

The strongest claim in the copy, and the one an attorney would look at hardest. It survives because it is specific and true: “confirmed twice” names the two artefacts, both are produced by the locked confirmation block at Appendix A.5, both are stored, and both are shown to the broker on the screen at §2.

Compare it with the claim it could have been — “high-quality appointments”, or “qualified leads”. Those are unfalsifiable, which sounds safe and is the opposite: an unfalsifiable claim cannot be substantiated when a consumer or a regulator asks. A specific claim with an evidence trail can be.

“Never for dials, never for maybes” is the same discipline applied to the billing model, and it constrains the product permanently: the platform cannot later introduce a per-dial charge without contradicting its own published copy. That is a constraint worth accepting, and worth knowing that you have accepted.

B.4 — The AI disclosure, handled as an asset“Will clients know it’s AI? (Yes — we disclose it, and it books better because it never has a bad day.)”

The obligation from Appendix A.2 is turned into a selling point rather than buried in an FAQ. The parenthetical answers the broker’s real worry — that disclosure will cost them bookings — with the argument that consistency beats charisma over a large number of calls.

Worth preserving as written. A future edit that softens this to “advanced technology” or similar would create a gap between the public copy and what the AI says on the call, and the call is recorded.

B.5 — The microcopy that protects the record“2 meetings need outcomes. 10 seconds each, and your reports stay honest.” · “Verified: this client confirmed twice — on the call and by SMS.” · “This wording is required by law. Everything else is yours to edit.”

Three small strings, each doing a job larger than its size.

The outcome nag asks for data the platform needs for dispute resolution and reporting, and justifies the ask in the same breath — “your reports stay honest” frames it as the broker’s interest, which it is. Stating the cost (“10 seconds each”) is what makes it get done.

The QA tooltip puts the definition of “verified” exactly where the word appears, so the product’s central claim is explained at the point of use rather than in terms nobody reads.

The locked-block tooltip explains the constraint of Appendix A.1 without lecturing, and the second half — “everything else is yours to edit” — is what stops the first half feeling arbitrary. A broker who understands why a field is locked argues with it far less than one who does not.

One phrase to watch

The pricing page says credits “never expire”. That is a strong, unqualified commercial promise, and it is the kind of clause that reads as harmless in marketing copy and becomes a liability on a balance sheet: unexpired credits are a standing obligation that never ages out, and they must be honoured indefinitely or the copy was untrue.

It is not wrong, and there is a good argument that it is a genuine differentiator against subscription competitors. It should be a deliberate decision rather than an inherited one, it needs to match the Terms of Service exactly, and it is worth confirming when B1 is settled. Flagged here rather than changed, because it is a commercial call and it is yours.

The compliance lint, rule by rule

The lint checks a submitted script before it reaches a human reviewer. This appendix documents what it checks and why each rule has the severity it has, because the severities are where the design argument lives. Source: apps/api/src/modules/scripts/script-lint.ts. The rules implement CF-DOC-01 §5.2.

Errors — the four mandatory disclosures

Only one class of finding blocks submission outright: a missing or tampered mandatory disclosure. These are the four clauses of Appendix A.1 — recording, AI, opt-out, identification.

Because those clauses live in locked blocks that a broker cannot edit, the lint is not the primary control here. It is a tamper detector: it verifies that the locked text actually still carries each required element, so a script whose locked block was emptied by a bug, a bad migration or a direct database edit cannot pass. Defence in depth, on the four statements that must never be absent from a call.

Warnings — advice, claims and statistics

Everything else is a warning: it annotates the script and sends it to the reviewer rather than rejecting it. The patterns are:

Advisory rules and what each is looking for
RuleCatchesWhy it is a warning, not an error
fais.advice_verb “I recommend”, “we suggest”, “I advise” Almost always advice, but a script may quote the phrase while telling the AI not to say it. A reviewer can tell the difference; a regular expression cannot.
fais.recommendation “you should invest / buy / switch / cancel” Same reasoning. The phrasing is the ordinary way a salesperson speaks, so it will appear in drafts written in good faith and needs teaching rather than blocking.
fais.comparative_claim “this policy performs better” A merit comparison between products is advice. Context occasionally makes it legitimate — quoting approved carrier material, for instance.
fais.financial_assertion “you’re paying too much”, “you’re losing money” A conclusion about this person’s finances, reached without seeing them. See Appendix A.3.
claims.guarantee “guarantee”, “guaranteed” Guarantees must come from the carrier’s approved wording. Sometimes they legitimately do, which is exactly why a human decides.
claims.statistic Any percentage or ratio — “20%”, “9 out of 10” CF-DOC-01 §5.2: no invented statistics. The lint cannot know whether a figure is substantiated; it ensures a person checks. This is the rule that catches the “20% discount” line noted at Appendix A.7.
claims.unsourced_generalisation “most people”, “nine out of ten South Africans” Population claims need a source. Note the deliberate near-miss: the approved “already covered” branch says “most people {broker} meets”, which is a claim about the broker’s own clients rather than a population — legitimate, and close enough to the line to deserve review.

Warnings — missing objection branches

The lint also warns when it cannot find handling for any of the five required objections: not interested, call me later, already covered, how did you get my number, and the hard opt-out (Appendix A.4). These are warnings because a script may cover a case in wording the patterns do not recognise, and a reviewer can see that where a regular expression cannot.

Why the lint advises rather than blocks

This is the design decision in the appendix most worth defending, because “block non-compliant wording automatically” sounds obviously safer and is not.

Your own specification settles it — CF-DOC-01 §5.2 says advice-like phrases are “flagged for admin attention”, and §5.1 requires a human to approve every script regardless. The build follows that, and there are two independent reasons it is the right instruction.

A hard gate teaches brokers to defeat it. If “I recommend” is rejected on submit, the broker writes “I’d say you want” and passes. The advice is unchanged; only the wordlist has been evaded. The broker has learned to satisfy the filter rather than to understand the FAIS boundary — and the filter is a list of patterns, while the boundary is a legal principle. Advisory findings that name the rule broken are the version that teaches.

A hard gate degrades the human review that is the actual control. If the reviewer believes the lint has already rejected anything non-compliant, they stop reading carefully — and the lint is a set of regular expressions, incapable of judging a novel phrasing. Presenting the reviewer with annotations rather than a verdict keeps the responsibility where the competence is.

The exception proves the rule: the four mandatory disclosures are hard errors, because their absence is a matter of fact rather than judgement. Where a machine can be certain, it decides. Where it cannot, it informs a person who can.

Decision register and dependency map

The five decisions of §5, restated as a register: what each unblocks, what it costs to defer, and what it depends on. The purpose of the table is to make the sequencing visible — two of the five gate long-lead items that take calendar time rather than effort, and those are the expensive ones to leave open.

Open decisions, in the order they unblock the most
RefDecisionCost of deferring
D1 Lead source and consent wording Blocking — determines whether the calling model is legally defensible (§6.2), sets the retry policy (§6.3), and populates the “how did you get my number” branch (Appendix A.7). No portal work touching consent can be finalised without it.
A1 Register the domain Calendar time — gates Google’s OAuth review, which takes 2–6 weeks and cannot start. Every week of delay is added directly to the launch date. The cheapest item on the list.
D3 Whose accounts, billed where Calendar time — gates NCC registration, which is already legally required (§6.1), plus every production account and the Terraform apply. Harder to unwind later than to set now.
B1 Price per appointment Design churn — four screens and a Terms clause carry a placeholder until it lands (§9.2). Cannot be finalised before the §6.1 cleansing cost is known and allocated.
D2 Pilot brokers Build sequencing — determines which portal screens are built first and which calling model the first deployment can use. Deferring wastes effort rather than time.

The dependency chain worth noticing

Two chains run through the register, and both start with a decision that costs nothing to make.

A1 → Google OAuth review → calendar integration → the success definition. The product’s success test at §2 requires appointments to land in a broker’s calendar. That requires OAuth approval, which requires a verified domain, which requires a purchase. A registration that takes an afternoon sits at the head of a six-week chain that ends at the product’s central promise.

D3 → NCC registration → lawful operation. Registration names a legal entity, so the entity has to be decided first. This chain differs from the others in one respect worth stating plainly: the obligation is not waiting for launch. It has applied since 15 April 2026 to any direct marketer, and the clock is running now rather than from the day the first call is placed.

The remaining three decisions cost effort and churn rather than calendar time. If only two decisions are taken this month, A1 and D3 are the two that buy back the most, and D1 is the one that most determines what is built.