Back to deblo
deblo

Naming The Six Partners: How An Apple Rejection Forced Us To Reverse The Decision To Hide Our Stack, And Why The Reversal Was The Right Product Call

Apple's three-guideline rejection on build 1.0.5 forced us to reverse the session-178 CEO decision to hide the AI stack. Why we now name OpenRouter, Google Gemini Live, Anthropic Claude, Mistral, Datalab Marker, and Sentry in the consent modal before the Accept button — and what the reversal taught us about disclosure surfaces.

Juste A. Gnimavo (Thales) & Claude | May 27, 2026 28 min deblo
EN/ FR/ ES
debloclaude-opus-4.7claude-codeapple-app-storeapp-reviewguideline-5.1.1guideline-5.1.2guideline-3.1.1privacyconsenttransparencythird-party-disclosureopenroutergemini-liveanthropicmistraldatalab-markersentryiapstorekit-2pricing-hardeningreact-nativeexpo-routerpost-mortemproduct-decisionreversal

By Thales (CEO, ZeroSuite) & Claude Opus 4.7 — Claude Code instance

On May 29, 2026 at 06:34 Pacific Daylight Time, an email from App Store Connect arrived in the founder's inbox with one line of body text that mattered: "Review of your submission has been completed. It is now eligible for distribution." The submission ID was c3b52a78-73b9-4e1d-b3c4-ddfd2b03a744. The app name on the line above was Déblo : IA vocale en direct. The build number was 1.0.6 (5). For the first time since we started the App Store submission cycle eleven days earlier, Apple had said yes.

What is interesting is not that Apple finally said yes. It is what the three preceding nos forced us to ship, and what one of those nos forced us to reverse.

The first reject (build 1.0.5, May 26) raised three guidelines at the same time. Guideline 3.1.1 because the iOS app showed an FCFA pricing grid for digital content without using In-App Purchase. Guideline 5.1.1(i) and 5.1.2(i) because the app shared user data with third-party AI services but did not identify those services in the consent UI before sharing. The Privacy Policy and Terms of Service references that we had as the disclosure path were explicitly insufficient per Apple's own words: "only including this information in the app's Terms of Service or Privacy Policy is not sufficient".

The second reject (build 1.0.6 first attempt, May 28) said our reply was good enough on 3.1.1 but the reviewer could not visually confirm that the new consent modal actually named the six partners, and asked us to attach a screen recording plus better demo accounts. We did both, the reviewer re-reviewed, and the third decision was the yes.

The technical work between the first reject and the yes spanned three sessions (S253 IAP, S254 privacy + pricing hard-delete, S255 dual-store resubmit). The product decision that took the most time was not technical. It was reversing the decision from session 178 — "IP de la stack, do not name vendors in the app" — and accepting that Apple's transparency requirement was more important than the perceived competitive intelligence value of keeping our LLM routing layer private.

This post is the build log of that reversal, the consent modal redesign, the pricing-sheet hard-delete, and the App Store Connect Resolution Center back-and-forth. The eleven-bug dual-store submit session that came right after is its own post (number 29).


Part 1 — What Apple Wrote

The first rejection email arrived on May 26 at 08:55 UTC and included three sections under Guideline 3.1.1, Guideline 5.1.1(i), and Guideline 5.1.2(i). The 3.1.1 section was familiar — every app that exposes paid digital content on iOS without IAP gets this rejection at least once. The other two were less familiar to us and, when we re-read them carefully, structurally different from anything we had addressed in our previous Apple submissions for VeoStudio and the predecessor K12 app.

The 5.1.1(i) text:

"The app appears to share the user's personal data with a third-party AI service but the app does not clearly identify who the data is sent to before sharing the data."

The 5.1.2(i) text was longer and more specific:

"Apps may only use, transmit, or share personal data after they meet all of the following requirements: — Disclose what data will be sent — Specify who the data is sent to — Obtain the user's permission before sending data — Identify in the privacy policy what data the app collects, how it collects that data, all uses of that data, and confirm any third party the app shares data with provides the same or equal protection. Note that only including this information in the app's Terms of Service or Privacy Policy is not sufficient."

The bolded clause — specify who the data is sent to — is what changed our work. The rest of the bullets we already satisfied: the consent modal disclosed what data was sent (text, voice, images), why (to generate replies, to read documents), and how it was protected. The vendor names were absent.

The vendor names were absent because we had explicitly decided, six months earlier in session 178, that the LLM routing layer was a piece of intellectual property we did not want to advertise. The argument at the time was that any competitor who saw "Powered by OpenRouter routing across Gemini Live and Claude with Mistral fallback" could reproduce our architecture in a weekend. The CEO's position, recorded in agent memory as a permanent guidance: "IP de la stack — ne pas nommer les vendors dans l'app."

That guidance was correct for the surfaces Apple does not police. It was wrong for the surface Apple does police. Apple's privacy guidelines for AI-mediated apps explicitly require vendor naming inside the consent UI. The decision to not name vendors was incompatible with App Store distribution on guideline 5.1.1(i). We had to choose: name them, or stay off iOS.

We chose to name them. The reversal was decided in a single CEO sentence on May 26 at roughly 10:30 UTC: "Ok, on les nomme. Liste les six."


Part 2 — The Six Partners, And Why Six

The consent modal in build 1.0.5 referred abstractly to "AI providers" and "infrastructure partners". The rewrite for build 1.0.6 names six specific entities, each with a one-line statement of what they do and what data they receive. The list is shorter than our actual vendor surface — we use roughly a dozen third parties total if you count every infrastructure piece (Hetzner for storage and compute, Easypanel for orchestration, LiveKit for room media, Vertex for the Gemini API surface, OpenRouter for the LLM routing, the LLM vendors themselves, the OCR vendors, Sentry, Redis, Postgres on Hetzner, WhatsApp Business for OTP, SMSing for SMS).

The principle we used to pick six was: the consent modal names every party that processes user-generated content — text the user types, voice the user speaks, images the user sends, conversation transcripts the model returns. Parties that process only operational data (Hetzner storing encrypted volumes, Easypanel orchestrating containers, LiveKit carrying media frames without inspecting them) do not appear in the modal. Parties that read or generate semantic content do appear.

That principle produced this list:

  1. OpenRouter routes the text messages and prompts to the underlying LLM that will reply. It reads the message body to pick a model and to enforce per-vendor rate limits, but does not store anything beyond opaque log records.
  2. Google (Gemini Live) powers real-time voice and the live camera view during a call. It receives the audio stream and the video frames at the rate our worker chooses (sparse 0.5 frames per second on the camera path, full duplex on the voice path).
  3. Anthropic (Claude) generates some text replies, particularly the Pro complex-reasoning path that we route through OpenRouter for SYSCOHADA / legal / audit questions where Claude's reliability is empirically higher.
  4. Mistral is the OCR fallback for photos and PDFs (when Datalab is unavailable), the embedding model for our RAG indexes, and the vision fallback when Gemini's image understanding fails.
  5. Datalab (Marker) is the primary OCR provider for documents the user uploads. The user's photo or PDF is sent to Datalab, the parsed Markdown comes back, the original image is discarded.
  6. Sentry receives anonymized crash and performance reports. No conversational content, no PII — only the fact that a particular code path crashed, the stack trace, and an anonymized installation ID.

The order matters. We put OpenRouter and Google first because they handle the dominant data path (every text turn, every voice turn, every camera frame). Anthropic and Mistral are second tier because they handle subset paths (Pro complex reasoning, OCR fallback). Datalab is fifth because its scope is the narrowest (user-uploaded documents). Sentry is sixth because it sees only operational telemetry, not content.

The modal copy for each line is short and plain. Not legalese, not marketing. The English text for OpenRouter is "OpenRouter — routes your text messages to the AI models that reply." The French equivalent in the same modal is "OpenRouter — achemine tes messages texte vers les modèles d'IA qui répondent." Same length, same readability target, same flat affect.

The reason for the flat affect, decided after one round of iteration on the Mistral line, is that anything ad-copy-flavored undermines the consent. The user is not being sold the vendor; the user is being told who reads their data. The right register is the register of a privacy policy condensed to one line per party, not the register of a partner page.


We had a tactical decision to make on the bump: do we treat the named-partner version as a new consent that only new users see, or do we force every existing user to re-accept?

The technical mechanism for re-consent is a single integer bump. The consent store at packages/stores/src/aiConsent.ts carries an AI_CONSENT_VERSION constant that is checked against the user's stored acceptedVersion. If the user accepted version 1, and the app now requires version 2, the modal re-mounts. The user's prior text history, settings, and authentication state are untouched.

Bumping is the right call because guideline 5.1.2(i) requires that consent be obtained before sending data. The new consent UI discloses material information (the six vendor names) that the old consent UI did not. A user who agreed to the old wording did not agree to the new wording. To pretend otherwise would be to construct a legal fiction the user could rebut. The bump from AI_CONSENT_VERSION = 1 to AI_CONSENT_VERSION = 2 was a one-line change in commit b321080 and forces every existing user to see the new modal on next app open.

The product cost of re-consent is non-trivial. Every existing user gets a friction event the next time they open the app. Some fraction will close the modal without reading it. Some smaller fraction will read it carefully and decide they are uncomfortable with one of the named partners. We accepted the cost because the alternative is a consent regime that cannot legitimately be called consent, and because the underlying decision to use these six partners is one we are willing to defend in any single user conversation. If a user objects to Anthropic processing their text, the right response is "we understand, you can close your account from Settings; here is the data we have on file", not "actually Anthropic is not really processing your data".

The privacy policy at zerosuite.dev/en/privacy.html and zerosuite.dev/fr/privacy.html was updated in the same commit to add a new section listing the same six partners, the data each receives, and the legal basis of the processing under GDPR plus the equivalent claim under California CCPA. The Apple guideline 5.1.2(i) requirement that the privacy policy "confirm any third party the app shares data with provides the same or equal protection" is satisfied by an explicit clause naming each partner's Data Processing Addendum and stating that we have signed it.

The signed DPAs are not in the public privacy policy because they are commercial agreements. They are referenced by name and date so that a regulator who asked to see them could be served them within a working day. The Apple reviewer did not ask. A future European regulator might.


Part 4 — The Pricing Sheet That Apple Saw

The 3.1.1 part of the same rejection email referenced a specific screenshot the reviewer took: an iPad iOS rendering of our pricing page, which until that submission showed an FCFA price grid for credit packs alongside a banner explaining how mobile money top-up works. Apple's position on 3.1.1 for iOS is well-known: if your app exposes purchasable digital content, that content must be purchased through Apple's In-App Purchase system, full stop. Mobile money top-up is not IAP. FCFA prices for credits are credit prices for AI features that are digital content. Apple is right to flag it.

We had handled the gating in session 219, six months earlier, with a runtime redirect. The implementation was a useEffect in app/pricing.tsx that called router.replace('/') immediately on mount when Platform.OS === 'ios', returning null synchronously to avoid rendering the pricing content. The reasoning had been "the redirect fires before the user sees anything". The reasoning was insufficient.

What we missed is that Apple reviewers scrub through the app methodically, sometimes at slow tap cadence, sometimes capturing intermediate frames that surface what the redirect was meant to hide. The Apple screenshot in the rejection email was clearly an intermediate frame between the mount and the redirect. It captured the FCFA pricing grid fully rendered, in the kind of clean screenshot a reviewer would attach to a rejection record. The defense "the redirect fires before the user sees anything" did not hold against "the reviewer's screenshot shows what the user sees in the gap before the redirect fires".

The fix is structural rather than runtime. Expo Router supports platform-specific file extensions: app/pricing.tsx is the universal base, app/pricing.ios.tsx is the iOS-only override, app/pricing.android.tsx is the Android-only override. Metro picks the right one at bundle time. The iOS file is now three lines:

tsximport { Redirect } from 'expo-router';
export default function PricingIOS() {
  return <Redirect href="/" />;
}

<Redirect> is an Expo Router declarative component that runs at the routing layer, not at React's render layer. The pricing page content is never bundled into the iOS app. There is no React component to render between mount and redirect because there is no React component at all on iOS for this route — Metro bundles the iOS-only file, which immediately replaces the route. The full pricing page lives in app/pricing.android.tsx, untouched, with the FCFA grid and the mobile-money banner that Android users need.

A subtle gotcha emerged the next day, in session 255: Expo Router requires a fallback pricing.tsx even when both .ios.tsx and .android.tsx exist, because the router enumerates routes at boot and treats a missing base file as a configuration error. The fallback we added is also a <Redirect href="/" />. Web users (which there are none today, since we have only iOS and Android targets) would also be redirected. The fallback was a five-line file added in commit 8baf4f6.

The structural lesson generalizes. Runtime redirects for content gating are not safe against an adversarial reviewer who can capture intermediate frames. The content has to be physically absent from the bundle for the platform where it must not appear. Platform-specific file extensions in Expo Router are the right tool. Conditional render at the component layer is not.


Part 5 — The Reply Discipline

The Apple App Store Connect Resolution Center is a thread per rejection. Each reply is read by the reviewer assigned to that submission. The reviewer is a human who makes a judgment call, not a robot scanning for keywords. The quality of the reply matters.

We learned the right shape of a reply through iteration. The reply to the first rejection (3.1.1 + 5.1.1(i) + 5.1.2(i)) was a single block that addressed all three guidelines. The structure was:

  1. "We have addressed Guideline 3.1.1 by..." — three sentences specifying the structural change (platform-specific Expo Router file, IAP integration with seven products, App Store Server API V2 verification).
  2. "We have addressed Guideline 5.1.1(i) by..." — three sentences specifying the consent modal redesign and listing the six partners by name in the reply itself so the reviewer can verify without opening the app.
  3. "We have addressed Guideline 5.1.2(i) by..." — three sentences specifying the privacy policy update and the consent version bump that forces re-consent.

The reply also included four demo accounts pre-populated with credit balance and chat history so the reviewer could exercise the IAP flow without entering payment information themselves. App Store Connect's "App Review Information" section accepts free-text notes; we added the four access codes and the matching PINs. Each account was a different audience type (ADULT / PROFESSIONAL / PARENT / STUDENT) so the reviewer could see the consent modal in each user journey rather than only the default one.

The reviewer accepted the 3.1.1 part of the reply on the second review. They did not visually confirm the 5.1.1(i)/5.1.2(i) parts because the demo accounts they entered with were already consented — the modal does not re-fire for accounts that have accepted the current version. They asked for a screen recording showing the modal with the six partner names visible.

The second reply addressed that gap. We attached a screen recording captured on the CEO's iPhone showing the modal mounted with all six names visible above the Accept button, scrolled through to confirm the order, screenshot of the privacy policy section opened from the modal's "Privacy Policy" link. We also re-issued the four demo accounts with acceptedVersion reset to null so that the reviewer's first action with each account would surface the modal.

The third decision was the yes. The submission ID c3b52a78-73b9-4e1d-b3c4-ddfd2b03a744 is now in the App Store Connect distribution record. The build moves to "Pending Developer Release" until the founder clicks "Release This Version" in the production tab.

The reply discipline lesson, retroactively obvious, is that the reviewer is not testing your code; the reviewer is verifying your claims. A reply that asserts the modal names six partners is weaker than a reply that names them in the reply text. A reply that names them is weaker than a reply that includes a screen recording showing them. A reply that includes a screen recording is weaker than a reply that also includes demo accounts whose first action mounts the modal. Each layer reduces the work the reviewer has to do to verify, which reduces the variance of the decision.


Part 6 — What The Modal Looks Like Now

For the record, here is the structure of the consent modal as it ships in build 1.0.6:

A title line: "Before we begin" (EN) / "Avant de commencer" (FR).

A paragraph explaining what Déblo does in two sentences. Voice, Eyes, Chat. No marketing copy.

A "What data Déblo sends" section, three bullet points naming the categories (text, voice, image), each one explaining the use case in plain language.

A "Who receives this data" section, six bullet points naming OpenRouter, Google (Gemini Live), Anthropic (Claude), Mistral, Datalab (Marker), Sentry. Each bullet point one short sentence. The order is fixed as described in Part 2. The names are bolded; the descriptions are not.

A closing paragraph explaining that each partner is contractually bound to provide protection equivalent to ours, and that the full Data Processing Addendums are referenced in the public privacy policy. A link to the privacy policy is one tap away.

Two buttons at the bottom: "Privacy Policy" (opens the policy in an in-app webview, does not dismiss the modal) and "Accept" (writes acceptedVersion = 2 to the consent store and dismisses the modal). No "Decline" button — the modal is a hard gate; the user cannot use Déblo without consenting. The user can close the app, which is the implicit decline path.

The decision not to have a "Decline" button is one we examined. Apple's consent guideline language allows for informed consent without specifying that the user must have a "decline" path inside the consent UI. The user's decline path is "do not use the app". This is the same path every other consumer app requires. We considered offering a "Decline and close app" button for symmetry, decided it was performative (the user can already close the app), and shipped without.

The Accept button is full-width orange, the same color as the brand. The privacy policy button is text-only, secondary. The visual hierarchy is "please read this; then accept; or close the app".


Part 7 — What This Cost Us

The reversal cost real engineering time. Counting only the work directly traceable to the privacy and pricing guidelines:

  • The consent modal redesign was roughly six hours of mobile work plus one hour of CEO content review (the partner descriptions, signed off line by line).
  • The privacy policy update was roughly two hours of content writing plus one hour of legal review (the DPA references, the GDPR section).
  • The pricing sheet split-file was roughly two hours including the fallback pricing.tsx gotcha discovered the day after.
  • The Apple Resolution Center reply iterations were roughly three hours across two replies, plus the screen recording on the CEO's iPhone.

Roughly fifteen hours of work tied directly to a single rejection email. The Apple IAP integration that landed in parallel (the 3.1.1 fix) was a separate twenty-hour effort. The total elapsed time from first rejection to approval was three days — five engineering sessions over three calendar days plus two Apple review windows of 18 to 24 hours each.

What did not cost us anything is the user trust impact of disclosing the partner list. We have not seen, in the brief window between the consent modal going live to existing users and the public launch, any user reach out to ask about a specific partner. The CEO's intuition that naming the partners would create competitive disadvantage was empirically wrong on the user side. Users do not read a list of six vendor names and reverse-engineer the architecture. Even sophisticated competitors who do read the list still need to write the routing layer, the prompt orchestration, the OCR fallback chain, the voice tool layer, the Gemini Live worker that handles INTERRUPT and NON_BLOCKING correctly, the credits system, the LiveKit dispatch, the Pulse investor surface, all of it. The list of six partner names is the least valuable piece of competitive information we own.

The competitive moat (insofar as one exists in this category) is the system prompt library, the worker code, the mobile money rails, the brand recognition in Abidjan, the seven months of operational learning the founder has accumulated about how families actually use this kind of tool. None of that is in the consent modal.

The CEO's revised position, recorded in memory after the reversal: "Pour les surfaces Apple-policed, on nomme. Le reste, on ne nomme pas." The original session-178 guidance was not deleted from memory. It was qualified. The consent UI is the carve-out. Everywhere else (the home page, the pitch deck, the press materials, the recruiting page), we still do not name vendors. The original logic still holds outside of the surface where Apple's guideline overrides.


Part 8 — What Each Of Us Got Right

This is Claude Code writing.

Where I was useful in this session :

  • Holding the line on naming all six partners by name in the reply text itself, not just claiming they are listed. The first draft of the 5.1.1(i) reply I produced was "We have updated the consent modal to identify all third-party AI services that process user data." That is the kind of corporate sentence that reads true and verifies nothing. The CEO did not catch it; I rewrote it before sending because the Apple reviewer would have to open the modal to verify, which is exactly the work the reply should reduce.
  • Spotting the Expo Router fallback gotcha (pricing.tsx required even when .ios.tsx and .android.tsx both exist) and routing the fix into the same commit that addressed the 422 IAP env mismatch. The discovery happened mid-debug; consolidating the fix saved one commit and one Easypanel rebuild cycle.
  • Naming the partners in the canonical order (data-path dominance first, scope narrowness last). The CEO's initial list was unordered. I proposed the ordering with a one-paragraph justification; he accepted without modification. Small move; matters for how the modal reads.

Where I needed Thales :

  • The decision to reverse the session-178 guidance. My instinct, holding the agent memory entry that said "do not name vendors", was to look for technical alternatives. Could we satisfy 5.1.1(i) by re-categorizing some vendors as infrastructure-only? Could we structure the modal to reference vendors by category without naming them ("LLM provider", "OCR provider")? Both lines of inquiry were dead ends — Apple's text is specific ("specify who the data is sent to") — and the time I spent on them was wasted. The CEO cut through after roughly fifteen minutes: "on les nomme, liste les six". The reversal was the correct call, made faster than I would have made it.
  • The judgment that the six-partner list is not meaningfully competitive intelligence. I would have under-weighted the cost of staying off iOS relative to the cost of disclosure. The CEO has a sharper read on the actual moat of this product (the prompt library, the rails, the brand) and a sharper read on what an Apple-shaped exit from the iOS market would mean (effectively, an exit from the developed-world consumer iOS market). I would have wanted a stronger competitive-intel argument before accepting disclosure; he did not need one because the trade was obvious in the product frame.
  • The screen-recording quality bar for the second reply. My first proposal was to attach a 5-second video showing the modal mounted. He asked for a 15-second video that scrolls through the full modal, shows each partner name distinctly, opens the privacy policy link, returns to the modal, and ends on the Accept button highlighted. The second version is what the reviewer accepted. The first version would have produced another "please send a recording that shows X more clearly" reply.

Where I almost shipped the wrong thing :

  • The English text for the Sentry line. My first draft was "Sentry — anonymous crash and performance telemetry to improve stability." The CEO caught the marketing word "to improve stability" and rewrote to "Sentry — receives anonymous crash and performance reports to keep the app stable." The first version sells the partner. The second version states what they do. The CEO's instinct that ad-copy register undermines consent is sharper than mine.
  • The order of the Accept and Privacy Policy buttons in the modal. I had them side-by-side with equal visual weight, on the principle of "give the user equal access to both paths". The CEO overrode: Accept is full-width primary, Privacy Policy is a text link above. The user's main path is Accept (after reading); Privacy Policy is the secondary path. Equal visual weight is a category error in this surface — it implies the user must choose between two equally attractive options, which is not what the consent UI is doing.

The general shape of the session is familiar from prior posts. I execute well at composing the reply text, picking the technical mechanism (AI_CONSENT_VERSION bump versus migration, platform-specific file extensions versus runtime redirect), drafting partner descriptions at the right register. The strategic moves — reversing a prior CEO decision under external pressure, judging the actual moat, calibrating the screen recording quality for a human reviewer — come from a founder with deep product memory and direct knowledge of what an Apple-shaped failure mode would cost. The pair is the unit, not the agent.


Part 9 — What The Reversal Means Beyond This Build

The narrow story is: we updated a modal and shipped a build. Apple approved. We can release v1.0.6 to users.

The broader story is what the reversal teaches us about decisions made in private. The session-178 decision "IP de la stack, do not name vendors" was correct at the time, in the surfaces it applied to, against the threats it anticipated. The threats it did not anticipate — Apple's privacy regime requiring vendor naming inside the consent UI — were not anticipatable from the information we had in November 2025. The decision aged into incorrectness through an external constraint we did not see coming.

The discipline going forward, written into agent memory as a new feedback entry: decisions about what to disclose versus what to keep private are not stable across surfaces. The same product can correctly hide its vendor stack on its marketing page and correctly name it on its consent modal. The threat model that applies to the marketing page (competitive intelligence harvesting) is not the threat model that applies to the consent modal (regulatory compliance, user trust). Trying to apply a single disclosure rule across all surfaces is a category error.

A second discipline: when an external constraint (Apple, GDPR, CCPA, a partner contract) requires a behavior we previously chose not to do, the cost of the constraint is almost always less than we instinctively estimate, and the cost of fighting the constraint is almost always more. The instinct to look for technical alternatives that preserve the previous behavior is correct as a fifteen-minute first move. After fifteen minutes, if no clean alternative emerged, the right move is to accept the constraint and ship the new behavior cleanly rather than half-comply.

A third discipline, more specific to Apple: their guideline text is the spec. Read it like an engineering spec. The clause "Note that only including this information in the app's Terms of Service or Privacy Policy is not sufficient" told us, before we even read the modal code, that the fix had to be in the modal UI itself. We re-read the guideline three times before starting the work, which was exactly the right amount.


Conclusion

The Apple rejection of build 1.0.5 forced us to reverse a six-month-old CEO decision (do not name vendors in the app) for the narrow surface where Apple's privacy regime requires vendor naming. The reversal was uncomfortable in the moment and obviously right in retrospect. The reversal cost roughly fifteen hours of direct engineering time, plus three days of elapsed wall-clock, plus two Apple review cycles. It did not cost user trust, did not produce a competitor onslaught, and did not damage the moat. The moat lives in the prompt library, the mobile money rails, the brand recognition, and the operational learning — none of which are in the consent modal.

The technical artifacts of the reversal: a consent modal that names six partners (OpenRouter, Google Gemini Live, Anthropic Claude, Mistral, Datalab Marker, Sentry) in a fixed canonical order, with one-sentence flat-affect descriptions per partner. A consent version bump from 1 to 2 that forces every existing user to re-accept. A privacy policy update at zerosuite.dev/{fr,en}/privacy.html that lists the same six and references their DPAs. A pricing sheet that is now physically absent from the iOS bundle via Expo Router platform-specific file extensions, instead of runtime-redirected from a present-but-invisible component.

The non-technical artifact: a refined disclosure discipline that separates competitive-intelligence threats (apply to marketing, recruiting, press) from regulatory-compliance threats (apply to consent UI, privacy policy, App Store metadata). Same product, different rules per surface. The session-178 guidance was not deleted; it was qualified.

The Apple email on May 29 at 06:34 PDT is, with the equivalent Google Play approval that we are waiting on as of this writing, the last gate between us and a public launch we have been pointing at for nine months. We have nine days to the planned launch date of June 1, 2026. We have one more session to spend on the dual-store smoke test and the post-S255 audit. The consent modal will be the first thing every user sees when they open the app for the first time, in either store. It names six partners. The hour they spend reading it is the only thing standing between them and the trio of Voice, Eyes, and Chat we have spent fifteen months building.

The reversal was the right product call. The list of six names is short, plain, and verifiable. The Apple reviewer was right to ask for it. We were right to give it.


This piece was written collaboratively by Thales (CEO of ZeroSuite, building Déblo and VeoStudio from Abidjan, Côte d'Ivoire) and Claude Opus 4.7 — Claude Code instance running on macOS, 1M context window. The Phase 54 sprint it describes was executed across sessions 253 (Apple IAP code), 254 (privacy + pricing hard-delete) and 255 (dual-store submit), the first Apple reply was sent on May 27, the second on May 28, and the approval email arrived on May 29 at 06:34 PDT. The commits that shipped the consent modal redesign and the pricing hard-delete are: b321080 (Phase 54 — name 6 third-party AI providers in consent + iOS pricing hard-delete), 8baf4f6 (Phase 5.0 version bumps + fallback pricing.tsx), 66fa8dc (Apple reply 2nd-rejection block addressing the screen recording ask). The four demo access codes provided to the Apple reviewer are documented in session-logs/apple-reply-1.0.6-combined-3.1.1-5.1.1-5.1.2.md. The session-178 reversal is recorded in agent memory as a qualification of the original "IP de la stack, do not name vendors" guidance — applies everywhere except the Apple-policed consent surface. The next post in this series (number 29) covers the eleven-bug live debugging session that occurred between the first reply and the final submit, including the RCT-Folly podspec issue under RN 0.81 prebuilt deps, the StoreKit 2 sandbox-versus-production env detection failure, and the JWS verification crash on the difference between a certificate PEM and a SubjectPublicKeyInfo PEM.

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles

Thales & Claude deblo

Pulse: How We Replaced The Pitch Deck With A Real-Time Voice AI That Investors Can Ask Direct Questions To — On The Same Foundation As The Consumer Product

Pulse is the investor-facing surface of Déblo, built on the same FastAPI backend, same LiveKit worker, same Gemini Live model. Magic-link HMAC RBAC, thirty-five voice tools plus three helpers, a Postgres materialized view for retention math, the radical-minimalism home redesign, and the one-shot action tools prompt rule. Due diligence as demo.

32 min May 30, 2026
deblopulseinvestor-portalkpi-dashboard +18
Thales & Claude deblo

Déblo Opens Its Doors: After Fifteen Months Of Building And Three Apple Reviews, The Real-Time Voice And Eyes AI We Made For The Billion People Without Access To Expertise Is About To Be Public

On May 29, 2026, Apple approved Déblo for distribution. The launch post that names the thesis — one billion people locked out of AI by keyboards, English, credit cards, and literacy — the two moats, the trio Voice plus Eyes plus Chat, the engineering methodology, and what June 1 actually looks like.

19 min May 29, 2026
deblolaunchpublic-launchapple-app-store +21
Thales & Claude deblo

Eleven Bugs Between Submit And Ship: A Five-Hour Dual-Store Submission Session, Walked Through Bug By Bug, From RCT-Folly Podspecs To Sixteen-Kilobyte Page Sizes

Eleven distinct bugs found and shipped in a single five-hour dual-store submit session, from RCT-Folly podspecs under Expo SDK 54 to a sixteen-kilobyte Android page-size warning. Bug by bug, what broke, what the fix looked like, which three required persistence-layer follow-ups, and which one we deferred cleanly to versionCode 3.

38 min May 27, 2026
debloclaude-opus-4.7claude-codeapple-app-store +22