ADR-0014: Compliance baseline (M1/M2)¶
- Status: Accepted
- Date: 2026-04-28
- Deciders: MASTER
- Related: RFC-0005, #40, Reference → Legal + compliance baseline, ADR-0003 anonymous build cookie, ADR-0004 English-only M1/M2, ADR-0011 monetisation rates, ADR-0012 security controls posture, ADR-0013 AI discoverability posture, #11, #14, #17, #28, #29, #41
Context¶
RFC-0005 surfaced five operational compliance decisions where Lebanese law is materially thinner than EU/US, but where punting past launch carried real risk: under-comply and the project gets exposed to reputational, contractual (affiliate-network audit), and post-launch statutory enforcement risk; over-comply and we ship slower with friction the Lebanese market doesn't expect. The reference doc (docs/reference/legal-compliance.md) carries the underlying research; eleven items (L1–L11) are flagged for Lebanese lawyer review before public launch.
961tech ships in Lebanon, monetises via affiliate links, collects email for price-drop alerts, persists anonymous build state in a signed cookie (ADR-0003), logs outbound clicks (with hashed IP) for affiliate reconciliation. Lebanese law has no operational DPA, no cookie statute, no FTC-style affiliate-disclosure rule, and Law 659/2005 may not even reach a non-selling aggregator.
This ADR is the engineering posture at M1/M2 — the part that can't punt to the lawyer and can't punt past launch.
Decision¶
Decision 1 — Cookie banner: defer past M1. No banner at M1. The only cookie at M1 is build_session (signed, functional, ADR-0003) — strictly-necessary scope under both Lebanese and EU rules; consent not required. Privacy policy includes a "what cookies we use" section. Triggers to add a banner: (i) we add non-essential cookies (analytics / advertising / third-party tracking); (ii) EU traffic exceeds the ADR-0004-shape >5% threshold; (iii) an affiliate network's audit posture requires it.
Decision 2 — Affiliate disclosure: footer + per-card line + /transparency page. PCPartPicker shape. Three surfaces:
- Sitewide footer line — "961tech earns commission on qualifying purchases via partner links."
- Per-card affordance on every UC-2 deep-link button — small
(affiliate)annotation or icon + tooltip. /transparencypage — full disclosure: CPS rate (1.5% per ADR-0011), no payment for placement, ranking criteria, public affiliate code-of-conduct.
This is FTC-shape compliant if 961tech ever surfaces to US-traffic scrutiny, fully sufficient under Lebanese Law 81/2018 / Law 659/2005's general no-misleading principle, and a clear trust play in a genre where transparency pages are rare (competitive-landscape.md §3.6).
Decision 3 — ToS + Privacy Policy: AI-assisted draft, then Lebanese lawyer review. ~1 day MASTER on the AI-assisted draft + ~$300–800 lawyer review fee. AI covers ~80% (GDPR-shape boilerplate, structure, retention table per Decision 4); lawyer answers the L1–L11 register items in legal-compliance.md §1.4, signs off on L3 (Arabic-disclosure language), and reviews the L5 Arabic disclaimer translation (Decision 5). Blocks public launch; does not block M1 internal/closed dogfooding. Filed as a follow-up issue from this ADR.
Decision 4 — Data retention windows (per-flow):
| Data | Retention |
|---|---|
build_session cookie / server session |
365 days from last activity |
| Auth.js account (#11) | Lifetime of account + 30 days post-deletion grace, then hard-delete |
| Price-drop email subscription (#14) | Until unsubscribe + 30 days for audit |
| Click logs (hashed IP, retailerId, listingId, ts, UA) | 90 days rolling |
| Affiliate conversion records | 24 months |
Enforced at the DB / cron layer in #29 DB architecture. 90-day click-log retention is the load-bearing privacy concession (post-Breyer hashed-IP-as-PII conservative reading); 24-month conversion-record retention matches Lebanese tax-accounting practice (BIC declarations + dispute window). The 90d click window is also long enough for affiliate reconciliation (UC-L) which typically has 30–60 day postback windows; cross-check with #17 affiliate reconciliation before lock.
Decision 5 — Liability disclaimer: per-listing card + ToS, with Arabic translation of the disclaimer. Every UC-2 deep-link card carries:
Prices scraped from
<retailer>at<timestamp>. Final price, currency, taxes, and stock state confirmed at retailer checkout. 961tech is not the seller.
…with a 3-sentence Arabic translation alongside the English. The Arabic translation hedges L3 (Arabic-disclosure language requirement) regardless of the lawyer's verdict — if the lawyer rules English-only is fine, the Arabic remains cheap defence-in-depth and doesn't contradict ADR-0004's English-only UI scope (this is a single 3-sentence disclaimer, not site-wide bilingual UI). ToS section in Decision 3's pass reiterates and expands the disclaimer for defence-in-depth on non-listing surfaces (build summary, share page, retailer profile). Lawyer reviews the Arabic translation in the same pass as Decision 3.
No L1–L11 register item is closed by this ADR. They flow to Decision 3's lawyer pass. The hedges in Decisions 1, 4, and 5 reduce engineering exposure on the high-stakes ones (L3, L4, L8) regardless of the lawyer's verdict; the lawyer pass closes the remainder.
Re-evaluation. Decision 1 reopens on its three triggers. Decisions 2 and 5 reopen if a Lebanese statutory rule lands on affiliate disclosure or per-listing labelling. Decision 3 reopens once 961tech crosses MRR thresholds that justify a retainer relationship rather than a one-shot review. Decision 4 reopens if #17's actual reconciliation window exceeds 90 days, in which case click-log retention extends to match.
Consequences¶
Positive¶
- D1: zero cookie-banner UX work at M1. Trigger-based posture is defensible under both Lebanese and EU rules. Doesn't pre-commit to a banner shape that we'd want to redesign once analytics is added.
- D2: PCPartPicker-shape disclosure is the genre's defensible upper bound; FTC-shape compliant; a clear trust play. Per-card affordance is small enough not to add density bloat.
- D3: cheapest defensible legal posture — lawyer's billable hours are minimised because AI handles the boilerplate. Lebanese-specific judgement (the L1–L11 register) lands where the lawyer can actually add value.
- D4: retention is enforced at the schema, not by policy or hope. 90d click window is privacy-friendly and audit-friendly. 24-month conversion records cover Lebanese tax-accounting and affiliate-network dispute windows.
- D5: per-listing disclaimer is the load-bearing liability allocator under Law 659/2005 Art. 4 / Art. 36. Arabic translation hedges L3 cheaply. Pairs with the per-listing freshness signal (
competitive-landscape.md§3.6) — same line carries trust + liability allocation.
Negative¶
- D1: Lebanese users are conditioned by Lebanese retailer sites to not see cookie banners; this is a non-cost. The cost lands later when we add analytics — banner UX work shifts to that point and becomes a forcing function for the entire consent UX.
- D2: ~1 day frontend cost. Per-card affordance must be tasteful; clumsy implementation undermines the trust play.
- D3: ~$300–800 lawyer fee is a real cash cost at M1 prototype scale. Public launch gated on completion of the lawyer pass — adds latency to public availability.
- D4: 90-day click-log retention is opinionated. If a future affiliate network requires 180-day postback support, retention has to extend — schema migration cost.
- D5: Arabic translation must be lawyer-reviewed (incompetent translation is worse than no translation). Adds ~30 minutes to the lawyer pass; minor cost.
Neutral¶
- This ADR does not draft any of the actual user-visible text (ToS, Privacy Policy, transparency page, per-card disclaimer copy, Arabic translation). Those drafts are follow-up tickets that inherit this ADR's constraints.
- This ADR does not address MASTER's personal tax-residency posture, commercial-entity choice (
commerçant individuelrecommended in RFC-0005 but lawyer-confirmed), or VAT registration trigger — those are L-register items handled in Decision 3's pass. - This ADR does not commit to monitoring L11 (VAT 11% → 12% Parliamentary enactment); that is a recurring project-board check, not an architectural decision.
Alternatives considered¶
D1 — Ship cookie banner at M1 with full toggles¶
Rejected. Friction the Lebanese market doesn't expect; over-engineering for the cookie scope we actually have (functional-only); pre-commits to UX we'd want to redesign once analytics is added. ~1 day work for zero current statutory benefit.
D1 — Ship "we use cookies" notice only¶
Rejected. Single-bar disclosure with dismiss is legally meaningless — neither Lebanese nor EU compliant on its own. Worst of both worlds: friction without compliance value.
D2 — Footer + transparency page only (no per-card line)¶
Rejected. Weakens FTC-shape compliance materially. Per-card affordance is the visible signal that a specific link is monetised; footer-only requires the user to remember a sitewide note when seeing each link.
D2 — Per-card prominent banner on every UC-2 card¶
Rejected. High visual density problem (competitive-landscape.md §3.7); over-discloses; trust signal noise.
D2 — Defer affiliate disclosure to public-launch ToS draft¶
Rejected. Even if statutorily silent, an affiliate-monetised site without any disclosure is the worst defensible posture — affiliate-network audit risk is immediate, not deferred.
D3 — Hand-roll ToS + Privacy Policy¶
Rejected. Solo non-lawyer drafting; misses statutory hooks; no defence on enforcement. ~2–3 days of MASTER's evening time saved; orders of magnitude more risk.
D3 — Hire Lebanese lawyer to draft from scratch¶
Rejected. ~$1,500–3,000 fee is the wrong slope for an M1 prototype that may pivot. Reserves bespoke drafting for the post-MRR retainer relationship.
D3 — Use a generator (Termly / iubenda / Cookiebot)¶
Rejected. Generic templates don't address Lebanese specifics — L3 Arabic disclosure, L4 LBP display, L8 hashed IP. Generators are adequate for EU/US but undersized for Lebanon.
D4 — Indefinite retention on all flows¶
Rejected. Privacy exposure unbounded; affiliate-network audit friction; post-Breyer hashed-IP-as-PII risk grows with retention duration.
D4 — 30-day click-log retention¶
Rejected. Too short for affiliate reconciliation cycles (UC-L typically 30–60 day postback windows). Breaks the reconciliation use case for a marginal privacy gain.
D5 — ToS-only liability disclaimer¶
Rejected. "We said so in the Terms" is a weaker liability allocator than "we said so on the card" under Law 659/2005 Art. 4 — Art. 4's "exact, sufficient, explicit information" standard is at the consumer-decision surface, which is the card.
D5 — Per-listing only, no ToS expansion¶
Rejected. No defence-in-depth on non-listing surfaces (build summary, share page).
D5 — Site-wide banner¶
Rejected. Friction + density similar to a cookie banner; same UX cost without the trust-signal upside of a per-listing freshness pairing.
D5 — Skip Arabic translation entirely¶
Rejected. L3 Arabic-disclosure language requirement is the single highest-stakes ambiguity in the Lebanese consumer-protection layer. Translation is ~3 sentences with negligible cost; skipping it carries real downside if the lawyer rules Arabic is required. The translation doesn't contradict ADR-0004's English-only UI scope — that ADR is about the interface, not about a single legal disclaimer.
References¶
- RFC-0005 — Compliance baseline (full evidence + per-decision rationale)
- Reference → Legal + compliance baseline (per-surface gap analysis vs Lebanese law; L1–L11 register)
- Reference → Competitive landscape §3.6 — transparency-page genre gap (D2 rationale)
- Reference → Competitive landscape §4.4 — Lebanese aggregator banner conventions (D1 rationale)
- ADR-0003 anonymous build cookie persistence — D1 surface (functional-only at M1)
- ADR-0004 English-only M1/M2 — D1 trigger threshold + D5 Arabic-translation precedent
- ADR-0011 monetisation rates — D2 transparency-page CPS-rate disclosure source
- ADR-0012 security controls posture — Q4 reopens on D4 retention obligations
- ADR-0013 AI discoverability posture — robots.txt declares; #44 enforces; D5 disclaimer pairs with the per-listing freshness signal
- #40 — RFC parent ticket
- #11 Auth.js integration — implements D4 auth-account retention
- #14 price drop alerts — implements D4 email-subscription retention
- #17 affiliate reconciliation S2S postback — D4 click-log window cross-check
- #28 page design — implements D2 per-card affordance + D5 per-listing disclaimer
- #29 DB architecture review for scale — implements D4 retention enforcement
- #41 monetisation — implements D2
/transparencypage