RFC-0005: Compliance baseline¶
- Status: Draft
- Author: MASTER
- Date: 2026-04-28
- Related: issue #40,
docs/reference/legal-compliance.md, ADR-0003, ADR-0004, #11, #14, #17, #28, #29, #41
Summary¶
Five operational decisions covering 961tech's compliance posture at M1/M2 launch. Drawn from docs/reference/legal-compliance.md — the underlying research is there. This RFC is the layer where MASTER picks, with eyes open, between options of comparable evidentiary support. Each decision: options, recommendation, rationale, what's at stake if we get it wrong.
Motivation¶
961tech ships in Lebanon, monetises via affiliate links, collects email addresses for price-drop alerts, persists anonymous build state in a signed cookie (ADR-0003), and logs outbound clicks (with hashed IP) for affiliate reconciliation. Lebanese law is materially thinner than EU/US — there's no operational DPA, no cookie statute, no FTC-style affiliate-disclosure rule, and Law 659/2005 may not even reach a non-selling aggregator. The reference doc lays this out; eleven items are flagged "needs lawyer review" before public launch.
What's left for this RFC is the engineering posture at M1/M2 — five decisions where we can't punt to the lawyer and can't punt past launch. The cost of getting them wrong is real: under-comply and we expose the project to reputational, contractual (affiliate networks), and statutory (post-launch enforcement evolution) risk; over-comply and we ship slower with friction the Lebanese market doesn't expect.
Proposal¶
Five decisions, each numbered. Recommendations are baked into the language but every one has explicit options for MASTER to redirect.
Decision 1 — Cookie banner: ship at M1 or defer?¶
Context. The only cookie planned at M1 is build_session (signed, functional, ADR-0003). No analytics, no advertising, no third-party tracking. Lebanese law has no cookie statute. GDPR/ePrivacy exempts strictly-necessary cookies from consent.
Options.
| Option | Description | Cost | Risk |
|---|---|---|---|
| A — Defer past M1 (recommended) | No banner. Privacy policy includes a "what cookies we use" section. Add banner only when (i) we add non-essential cookies, (ii) EU traffic exceeds an ADR-0004-shape threshold, or (iii) an affiliate network requires it. | Zero | Low — strictly-necessary scope under both Lebanese and EU rules. If we add analytics later, banner is mandatory then. |
| B — Ship at M1, generic | Cookie banner with "essential / analytics / marketing" toggles + a "Accept all" / "Reject" pair. | ~1 day frontend + accessibility QA | Medium — banner UX adds friction the Lebanese market doesn't expect; over-engineering for the cookie scope we actually have. |
| C — Ship at M1, "we use cookies" notice only | Single-bar disclosure with a dismiss; no consent collection. | ~2 hours | Low statutory; legally meaningless — neither Lebanese nor EU compliant on its own. |
Recommendation: A — defer past M1.
Rationale. The cookie surface at M1 is functional-only. Adding a banner solves no problem we have, adds friction Lebanese users don't expect (no Lebanese aggregator currently shows one — see competitive-landscape.md §4.4), and pre-commits to a UX surface we'd want to redesign once we add analytics. The trigger-based approach mirrors ADR-0004's "revisit if EU traffic >5%" pattern — defensible engineering posture, not regulatory neglect.
What's at stake if we choose wrong. Under-comply (A but later add analytics without a banner) → real GDPR exposure once EU traffic crosses Art. 3(2) extraterritorial threshold, plus affiliate-network audit risk. Over-comply (B at M1) → friction, ~1 day of work, harder to redesign cleanly when scope changes.
Decision 2 — Affiliate disclosure: shape and placement¶
Context. No Lebanese rule mandates affiliate disclosure. FTC 16 CFR §255 (US) and EU UCPD (EU) do, with prescriptive language. We will run paid affiliate links — disclosing is cheap, defensible, future-proof, and conforms to Lebanese Law 81/2018 / Law 659/2005's general no-misleading principle without any statutory ambiguity. The question is shape (text + placement) at the surface level.
Options.
| Option | Description |
|---|---|
A — Footer + per-card line + /transparency page (recommended) |
(i) Sitewide footer line: "961tech earns commission on qualifying purchases via partner links." (ii) Per-card single-line affordance on UC-2 deep-link buttons: small (affiliate) annotation or icon + tooltip. (iii) /transparency page explaining the model in detail (CPS rate, no payment for placement, ranking criteria). |
B — Footer + /transparency only |
Same as A without the per-card line. Lower visual cost; weaker FTC-shape compliance. |
| C — Per-card prominent banner | "AFFILIATE LINK" badge on every UC-2 card, no separate transparency page. High visual density — see competitive-landscape.md §3.7 for genre's existing density problem. |
| D — Defer ("we'll add it before public launch") | Skip until ToS draft. Not recommended — even if statutorily silent, an affiliate-monetised site without any disclosure is the worst defensible posture. |
Recommendation: A — footer + per-card line + /transparency page.
Rationale. This is the shape PCPartPicker ships (competitive-landscape.md §2.1). The transparency page is rare in the genre and a clear trust play (per §3.6 trust + transparency patterns). Per-card affordance is small enough not to add density bloat, large enough to satisfy FTC shape if 961tech ever surfaces to US-traffic scrutiny.
Implementation hook. #28 page design is the natural place; UC-2 deep-link card is where the per-card affordance lives; /transparency becomes its own small surface filed under #41 monetisation.
What's at stake if we choose wrong. Under-disclose → reputational risk, affiliate-network audit risk. Over-disclose (C) → density and trust signal noise on every card.
Decision 3 — ToS + Privacy Policy: hand-roll, AI-assisted-then-lawyer, or hire-Lebanese-lawyer?¶
Context. 961tech needs both documents at launch. Lebanese law has no prescribed content list for either. GDPR Art. 13/14 is the practical content template even though it doesn't bind us. Reference-doc §1.4 register has 11 items that need lawyer review; the ToS / Privacy Policy is the natural surface where those answers land in user-visible form.
Options.
| Option | Cost | Risk |
|---|---|---|
| A — Hand-roll | ~2-3 days of MASTER's evening time | High — solo non-lawyer drafting; misses statutory hooks; no defence on enforcement |
| B — AI-assisted draft, then Lebanese lawyer review (recommended) | ~1 day MASTER + ~$300-800 lawyer review fee | Low — AI handles structure / GDPR-shape boilerplate; lawyer signs off on Lebanese-specific items (L1-L11 in reference doc §1.4) |
| C — Hire Lebanese lawyer to draft from scratch | ~$1,500-3,000 fee | Lowest — but slow; over-engineered for an M1 prototype that may pivot |
| D — Use a generator (Termly / iubenda / Cookiebot) | ~$10-20/mo | Medium — generic templates don't address Lebanese specifics (L3 Arabic disclosure, L4 LBP display, L8 hashed IP); generator templates are adequate for EU/US but undersized for Lebanon |
Recommendation: B — AI-assisted draft, then Lebanese lawyer review.
Rationale. This is the "professional sign-off only on the calls that need it" stance. AI handles ~80% (boilerplate, GDPR-shape, structure); the lawyer answers the 11 register items + signs off on the language-of-disclosure question (L3) which is the highest-stakes ambiguity. Cheapest defensible path. Pairs cleanly with the launch timing — we don't ship public until the lawyer pass is done, and the lawyer's billable hours are minimised.
Implementation hook. Filed as a follow-up issue post-RFC: "Draft ToS + Privacy Policy from RFC-0005 baseline + lawyer review." Blocks public launch but does not block M1 internal/closed dogfooding.
What's at stake if we choose wrong. Hand-roll (A) → real exposure on the 11 register items, particularly L3 (Arabic disclosure conflict) and L4 (LBP display). Generator (D) → misses Lebanese specifics. Full-bespoke (C) → over-cost for an M1 prototype.
Decision 4 — Data retention windows: per data flow¶
Context. No Lebanese statutory minimum or maximum for any of our data flows. GDPR-default is "as long as necessary." Reference doc §4.4(b) recommended a per-flow table; this RFC formalises it for the architectural lock-in at #29 DB architecture.
Options. Each row is "ship the recommended retention" (recommended) vs "longer / shorter / TBD." Recommended values:
| Data | Recommended retention | Defensibility |
|---|---|---|
build_session cookie / server session |
365 days from last activity | Matches ADR-0003 cookie expiry; bounded |
| Auth.js account (#11) | Lifetime of account + 30 days post-deletion grace, then hard-delete | User expectation; affiliate-network audit-friendly |
| Price-drop email subscription (#14) | Until unsubscribe + 30 days for audit | CAN-SPAM-shape; EU-friendly |
| Click logs (hashed IP, retailerId, listingId, ts, UA) | 90 days rolling | Long enough for affiliate reconciliation cycles (UC-L, 30-60 days typical); short enough to limit privacy exposure |
| Affiliate conversion records | 24 months | Tax + accounting + dispute window |
Recommendation: ship the table as locked retention windows, enforced at the DB / cron layer in #29.
Rationale. GDPR-shape defensible across all flows. 90-day click-log retention is the load-bearing privacy concession (post-Breyer hashed-IP-as-PII conservative reading per §4.4©). 24-month conversion-record retention matches Lebanese tax accounting practice (BIC declarations + dispute window).
Implementation hook. Each retention window becomes a Prisma deletedAt / purgeAt column or a nightly cron job per table. Documented in #29 and surfaced in the privacy policy.
What's at stake if we choose wrong. Longer retention → privacy risk + affiliate-network audit friction. Shorter retention → broken affiliate reconciliation (UC-L) if the postback window exceeds our log retention.
Decision 5 — Liability disclaimer: per-listing or site-wide?¶
Context. Reference doc §3.4(1) identified the per-card price disclaimer as the single most load-bearing liability allocator under Law 659/2005 Art. 4. Question is placement: per-listing (every UC-2 card) or site-wide (footer / ToS only).
Options.
| Option | Description |
|---|---|
| A — Per-listing card + ToS (recommended) | Every UC-2 deep-link card carries: "Prices scraped from |
| B — ToS-only ("Read the Terms") | Single ToS section, no per-card disclaimer. Lower visual cost, weaker liability allocation. |
| C — Per-listing only | Card disclaimer with no expanded ToS section. Defensible at the card surface, weaker on the rest of the site. |
| D — Banner across the site | Persistent disclaimer bar (top of page or footer) — high visual cost, similar to a cookie banner. |
Recommendation: A — per-listing card + ToS.
Rationale. The per-card disclaimer + last-updated timestamp + "961tech is not the seller" line allocates liability to the retailer of record on every UC-2 surface, where Law 659/2005 Art. 4 / Art. 36 "exact, sufficient, explicit information" exposure is highest. Pairs with competitive-landscape.md §3.6 "per-price freshness signal" UX adoption — same line carries both the trust signal and the legal allocator. ToS expansion provides the defence-in-depth.
Implementation hook. #28 page design — per-listing card layout. ToS section follows from Decision 3 implementation.
Pair with Arabic translation of the disclaimer (per §3.4(7)). This is the proposed L3 mitigation: ~3 sentences in Arabic alongside the English disclaimer, neutralising the most plausible "language of disclosure" attack vector under Law 659 Art. 4 without contradicting ADR-0004. Surface in the same per-card spot, lawyer reviews the translation in Decision 3's pass.
What's at stake if we choose wrong. B (ToS-only) → weak per-card allocation; if a user sues over a stale price, "we said so in the Terms" is weaker than "we said so on the card." D (banner) → friction + density. C (per-listing only) → no defence-in-depth on non-listing surfaces (e.g. build summary, share page).
Trade-offs¶
The cumulative shape: ship M1 with no cookie banner, full per-listing disclaimer + Arabic translation of just that disclaimer, three-line affiliate disclosure (footer + per-card + transparency page), retention windows enforced at the schema, and a ToS / Privacy Policy drafted with AI assistance + Lebanese lawyer review before public launch. No "needs lawyer review" item from §1.4 is closed by this RFC — they go to the lawyer as part of Decision 3's pass.
Costs accepted:
- ~1 day MASTER frontend on per-card disclaimer + affiliate disclosure + transparency page (Decision 2 + 5).
- ~1 day MASTER on ToS / Privacy Policy AI-draft (Decision 3).
- $300-800 Lebanese lawyer review fee (Decision 3).
- Schema-level retention windows in #29 (Decision 4).
- ~3 sentences of Arabic translation (Decision 5 — Lebanese lawyer can do this in the same review pass).
Costs deferred:
- Cookie banner UX (Decision 1 trigger-based).
- Full Arabic / French i18n (ADR-0004 revisit triggers).
- Bilingual ToS / Privacy Policy (Decision 3 — defer until L3 has a confident answer or until ADR-0004 revisit).
Alternatives¶
The "do nothing until launch" baseline is rejected. Lebanese law's thinness creates room, it doesn't eliminate the affiliate-network contractual layer or the EU-traffic GDPR Art. 3(2) extraterritorial vector. Affiliate networks (Awin / Impact / CJ / Amazon) audit privacy posture; "we have no privacy policy" closes those doors before they're open.
The "defer everything to a Lebanese lawyer from scratch" baseline is rejected on cost — $1,500-3,000 for an M1 prototype that may pivot is the wrong slope.
The "hire a Lebanese lawyer to embed and rewrite the entire compliance posture" baseline is rejected on scope — 11 register items (L1-L11) is a half-day of focused review, not a retainer.
Open questions¶
- L3 (Arabic disclosure language requirement). This is the single highest-stakes ambiguity. Decision 3's lawyer pass closes it; Decision 5's Arabic-disclaimer mitigation is the engineering hedge in case the lawyer says "yes, you need Arabic." If the lawyer says "no, English-only is fine," the Arabic translation is still cheap defence-in-depth and doesn't contradict ADR-0004.
- L1 (commercial register registration trigger). Decision 3's lawyer pass closes it. Practical answer is probably "register pre-launch, before first paid affiliate contract" — but MASTER may decide to defer until first revenue lands.
- L11 (VAT 11% → 12% Parliamentary enactment date). Track via the Ministry of Finance / official gazette; affects affiliate invoice template once enacted.
Implementation plan¶
- Open follow-up issue: Draft ToS + Privacy Policy (Decision 3) — AI-assisted draft + Lebanese lawyer review. Blocks public launch.
- Open follow-up issue: Per-listing disclaimer + affiliate disclosure surface (Decisions 2 + 5) — feeds #28 page design.
- Update #29 DB architecture with the retention table from Decision 4.
- Update #41 monetisation with the affiliate-contract template + featured-listing labelling baseline.
- Track L11 (VAT 12% enactment) as a recurring check in the project board until enacted.
Out of scope¶
- Drafting the actual ToS / Privacy Policy text (follows from Decision 3 implementation).
- Drafting the actual cookie banner UX (deferred per Decision 1).
- Drafting the actual affiliate-contract template (follows from #41).
- Closing any of the L1-L11 register items — those are explicit lawyer questions, not RFC decisions.
- Any decision about MASTER's personal tax-residency posture or commercial-entity choice (SAL / SARL / individual trader). The RFC recommends
commerçant individuelregistration but MASTER may take a different path on professional advice.