docs(legal): dedicated Privacy Notice separate from T&Cs 1.5 #35
Labels
No labels
agent:implement
agent:ready
api
bot
bug
ci
enhancement
ready
security
terra-classic
testing
ux
web
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-ecosystem-legal#35
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Publish a dedicated Privacy Notice as a first-party HTTPS document, separate from T&Cs Version 1.5, then link it from the four product footers.
T&Cs
Version: 1.5(TERMS_AND_CONDITIONS.txt) has no privacy / cookies / data-processing section. TermsGate,@cl8ytermsbot, the DEX indexer, WalletConnect / Reown, Coinbase Wallet SDK, request logs, and first-party agent-box tool connectors already process data. None of that is disclosed in a document a visitor can open from the footer.This issue is the canonical notice +
https://terms.cl8y.com/privacy+ footer links. It does not absorb SPA legal-guess routing, storage-consent / idle SDK init, or TermsGate coverage parity. Those stay on the issues named below.Bundle (do not split):
content_sha256re-sign path.https://terms.cl8y.com/privacy(portal route; optional read-only API content route that is not bound into acceptance messages).cl8y.com,dex.cl8y.com,bridge.cl8y.com, andterms.cl8y.com, all pointing at that same HTTPS URL.Decisions (do not re-litigate unless product changes them):
TERMS_AND_CONDITIONS.txt.https://terms.cl8y.com/privacy(exact origin + path, HTTPS, no query/hash).cl8y.com/privacymust not fall through to T&Cs home (renderHome).Not a duplicate of:
/privacymust not paint Swap / Transfer / homepage). That issue says 404 until a canonical notice exists; authoring the notice is out of scope there. After this URL exists, #12 may 301 reserved paths to this constant.Current codebase
Legal platform (
code/cl8y-ecosystem-legal) — this worktreeTERMS_AND_CONDITIONS.txtVersion: 1.5, effective 10 August 2026. Privacy appears only as incidental “privacy laws” language. Hash-aware oracle inapi/src/terms/sync.rsbindscontent_sha256into wallet/Telegram acceptance messages (api/src/message.rs).https://terms.cl8y.com.web/src/main.tsroutes `/sign/evmhttps://api.terms.cl8y.com. Terms routes:GET /api/v1/terms/latest,/terms/latest/content,/terms/{version_label}. Signature routes:GET /signatures/status,POST /signatures/wallet,POST /signatures/telegram. No privacy document route.packages/cl8y-clickwrap—TermsGatepollsproperty+network+account. Networks:EVM/TerraClassic/Solana/Telegram.VITE_WC_PROJECT_ID(Reown Cloud) for/sign/evmand Galaxy Station WC v2 on/sign/terra-classic(web/src/evm/walletConnect.ts,web/src/terra/walletConnect.ts). No@reown/*direct import; no Coinbase Wallet SDK in this repo.tower_httpTraceLayeron the API. Client IP is used for in-memory rate limits only (api/src/rate_limit.rs: TCP peer by default; rightmost XFF hop only insideTRUSTED_PROXY_CIDRS). IPs are not columns onsignatures/terms_versions/ bot tables.TermsGate / signature fields actually persisted (
api/migrations/001_initial.sql,WalletSubmitBody/TelegramSubmitBodyinapi/src/routes/signatures.rs):property,network,account_id,message,signature, optionalpubkey,client_timestamp, optionalversion_label; proof JSON{ type, signature, pubkey }.id,first_name,last_name,username,photo_url,auth_date,hash, or Mini Appinit_data. Stored:account_id= Telegram user id,account_display=@usernameif present, proof{ type, auth_date }or{ type, hash, auth_date }. Names/photos are used for hash verify, then dropped (not columns).Property,Network,Account,Content-SHA256,Accepted at (UTC)— T&Cs bytes only. Do not add Privacy Notice hash to this message.Telegram enforcement bot (
bot/, public README name@cl8ytermsbot):bot_chat_state:chat_id,last_known_version,last_reminder_atbot_member_compliance:chat_id,user_id,required_sinceThere is no
PRIVACY_NOTICE*file and no privacy version table.Marketing (
code/CL8Y-web) — sibling PRsrc/app/index.tsx:/, blog, legacy redirects, whitepaper. No/privacypage.SiteFooter.tsx+src/data/copy.ts: product / social / docs / disclaimer / law-enforcement. No Privacy link. No Terms link yet (#34 optional Terms href is separate and must stay named Terms).CANONICAL_PRODUCT_URLSinsrc/content/invariants.tsis Bridge + DEX only.AppProvidersmounts wagmi (injected+ optionalwalletConnectwhenVITE_WALLETCONNECT_PROJECT_IDis set,reconnectOnMount). No Connect UI. Transitive@reown/appkit/@coinbase/wallet-sdkin the lockfile; Coinbase connector not registered.index.htmlloads Google Fonts on every paint.DEX (
code/cl8y-dex-terraclassic) — sibling PRLegalFooterNotice.tsx(Security / Incidents / LP howto / Report) +cl8yProductLinks.ts(Homepage / Bridge). Product-link allowlist is onlycl8y.comandbridge.cl8y.com— a Privacy href toterms.cl8y.commust not be forced throughisAllowedCl8yProductHref.swap_events.sender/receiver,traders.address, LPprovider, limitowner/maker). Public trader APIs:/api/v1/traders/{addr}and related. No IP / UA / cookie columns. Peer IP is an in-memory rate-limit key (PeerIpKeyExtractor; XFF not trusted).TraceLayeron HTTP.@walletconnect/legacy-client+ cosmes; production CSP allowlistshttps://pulse.walletconnect.org. No Coinbase connector. Returning WC users auto-reconnect fromcl8y_wallet_connection(useWallet.ts).ConnectedTermsGate/legalClickwrap.ts, propertydex.cl8y.com. Risk ack is localStoragecl8y-dex-risk-ack, not this notice.Bridge (
code/cl8y-bridge-monorepo) — sibling PRpackages/frontend/src/components/Layout.tsx: version / SHA / theme only. No legal links.createConfigat module scope:walletConnect({ projectId, showQrModal: true })whenVITE_WC_PROJECT_IDis set;coinbaseWallet()always with nopreference.telemetry: false. Reown AppKit is transitive only. Coinbase CCA / WC heartbeat are the idle third parties #165 gates.BridgeTermsGate, property pinbridge.cl8y.com.Agent-box connectors (first-party automated agents)
Allowlisted community / support messages can be turned into public engineering issues by first-party Cursor CLI agent boxes. Those boxes may invoke third-party model APIs and tool connectors (issue tracker; optional mail/social plugins when enabled).
Public outputs are anonymized issue text. The Privacy Notice must disclose this category (message content after redaction, public issue bodies, connector telemetry the vendors already document). It must not publish operational inventory (hosts, VMs, tokens, datastores, queue identifiers). Private-plane implementation stays in the private agent-control repo; do not copy runbooks into the notice.
Why this is needed
/privacy./privacyURLs currently impersonate product UI (#12). A real document at a stable HTTPS URL is the only honest redirect target; until then #12 correctly 404s./privacystill renders sign-home).This is legal document + static/portal serving + footer constants. No wallet crypto, no indexer schema change, no T&Cs oracle change, no CMP vendor.
Constraints and guardrails
TERMS_AND_CONDITIONS.txtor bumpVersion: 1.5. Privacy has its own label (e.g.Privacy-Notice-Version: 1.0) and its own hash if you publish one. Never bind Privacy SHA intobuild_acceptance_message.POST /update_termsfor this document.scripts/publish-terms.shstays terms-only.https://terms.cl8y.com/privacy.URL+ hardcoded origin and path. Never from query, hash,Referer,window.location, or envVITE_*redirect. Rejectjavascript:,data:,//, http, userinfo, ports.code/CL8Y-web,code/cl8y-dex-terraclassic,code/cl8y-bridge-monorepo. Do not patch siblings from a Legal checkout./privacyis notrenderHome. Sign routes unchanged. Home still requires?property=for T&Cs.innerHTMLof API/user content. NodangerouslySetInnerHTML. Portal already uses text nodes for T&Cs (signShell.ts).VITE_WC_PROJECT_ID/VITE_WALLETCONNECT_PROJECT_ID), Coinbase Wallet SDK / CCA (bridgecoinbaseWallet()), Telegramtelegram.orgscript + Login Widget / WebApp, Google Fonts on marketing, indexer public trader APIs, Legal API signature rows, agent-box model/tool vendors in generic terms.<a>.LegalFooterNoticeor equivalent), not a thirdCL8Y_PRODUCT_LINKSentry unless you also extendALLOWED_HOSTSand keep product vs legal distinct in tests.terra1…,0x…, numericuser_id).ADMIN_TOKEN, WC project ids, or bot tokens in the notice, tests, or screenshots.Relevant files
This repo (
code/cl8y-ecosystem-legal)PRIVACY_NOTICE.txt(new, repo root)TERMS_AND_CONDITIONS.txtTERMS_AND_CONDITIONS.txtweb/src/main.ts/privacyroute; stop default-to-home for that pathweb/src/pages/privacy.ts(new)web/src/pages/home.tsweb/src/signShell.tsweb/index.html/privacyis the T&Cs portalapi/src/routes/terms.rsapi/src/routes/privacy.rsread-only contentapi/src/message.rsapi/src/routes/signatures.rsapi/migrations/001_initial.sql,002_bot_state.sqlpackages/cl8y-clickwrap/src/react/TermsGate.tsxREADME.md/privacyvs terms oracleskills/(newprivacy-notice)web/e2e//privacyvs/vs/sign/*Sibling
code/CL8Y-websrc/content/invariants.tsPRIVACY_NOTICE_URL = "https://terms.cl8y.com/privacy"src/content/invariants.test.ts@/ redirectors / querysrc/components/chrome/SiteFooter.tsx+src/data/copy.tssrc/components/ui/ExternalLink.tsxe2e/*.spec.tsSibling
code/cl8y-dex-terraclassicfrontend-dapp/src/components/legal/LegalFooterNotice.tsxfrontend-dapp/src/components/legal/legalCopy.tsfrontend-dapp/src/utils/cl8yProductLinks.tsdocs/frontend.mddata-testidfor the Privacy linkSibling
code/cl8y-bridge-monorepopackages/frontend/src/components/Layout.tsxpackages/frontend/src/utils/clickwrap.tsdocs/FRONTEND_BRIDGE_INVARIANTS.mdpackages/frontend/e2e/Recommended direction
1. Source document (this repo)
Add
PRIVACY_NOTICE.txtwith a headerPrivacy-Notice-Version:andEffective date:. Counsel-edited sections must cover, as separate headings:cl8y.com,dex.cl8y.com,bridge.cl8y.com,terms.cl8y.com/api.terms.cl8y.com).property,network,account); wallet submit fields; Telegram widget /init_dataverify-then-drop; what is stored insignatures.@cl8ytermsbotcompliance tables (chat_id,user_id); reminders / kicks as processing purpose; no claim that names/photos are stored if they are not.coinbaseWallet(); marketing/DEX do not; CCA / telemetry as current-code risk until #165.cl8y-theme, DEX risk-ack, bridge history, wagmi/WC session keys) as a factual list; point to #165 for refuse/accept. Do not invent a cookie policy page in this ticket (/cookiesremains #12).contact@ceramicliberty.comalready on the marketing footer. No new inbox product.Keep the body plain text. If HTML is served, generate from this file in the portal (text nodes /
textContent), neverinnerHTML.2. Serve on the Legal portal
case "/privacy":inweb/src/main.ts→ dedicated renderer.GET /api/v1/privacy/latest/contentreturningtext/plainfrom the file (or a dedicated table notterms_versions). If you skip the API, serving the static portal page is enough for AC./privacy; Terms remains the T&Cs flow. Do not label T&Cs as Privacy.3. Footer siblings (separate PRs, same constant)
ExternalLinkinSiteFooter, label Privacy, next to (not instead of) #34’s optional Terms href.·link inLegalFooterNotice,data-testid="privacy-notice-link".rel="noopener noreferrer",https:only.4. Coordination (not this implementer)
+1 canonical notice https://terms.cl8y.com/privacy — 301 now allowed.Acceptance criteria
PRIVACY_NOTICE.txtexists at repo root with its own version header.TERMS_AND_CONDITIONS.txtstillVersion: 1.5and byte-unchanged in the Privacy PR (or only an unrelated already-landed diff — this ticket must not edit it).GET https://terms.cl8y.com/privacy(prod or preview with the same path) returns the notice as a document, not the T&Cs home / sign chooser. HTTP 200. Title/OG do not claim it is T&Cs./,/sign/evm,/sign/terra-classic,/sign/solana,/sign/telegramstill behave as today (property required on home; sign shells unchanged except a Privacy footer link).api/src/message.rsstill bind T&CsContent-SHA256only. No Privacy hash in signed messages. Existing signature rows remain valid.hrefis exactlyhttps://terms.cl8y.com/privacy. It is not named Terms, Cookies, or Opt-out./privacyand sign/home includes the same path (absolutehttps://terms.cl8y.com/privacyor same-origin/privacythat resolves there).ADMIN_TOKEN, WC project id, bot token, or wallet/Telegram production identifiers in the notice, tests, or fixtures.#12routing work is not re-implemented here; siblings do not add a second invented/privacyHTML page on marketing/DEX/bridge that duplicates the notice body (link out, do not fork copy).Test plan (functional paths)
GET /privacyon Legal portal (Playwright, 5 workers)?property=requiredGET /without propertyGET /sign/evm?property=dex.cl8y.comGET /sign/telegram,/sign/solana,/sign/terra-classicGET /api/v1/privacy/latest/contenttext/plain(or 404 if API skipped — then T1 is the only serve path); not aterms_versionsrowGET /api/v1/terms/latest?property=dex.cl8y.comcontent_sha256still T&Csapi+ clickwrap)yarn test+yarn test:e2e --workers=5privacy-notice-linkhref exact; product links still only homepage/bridge; Swap/unaffected--workers=5gitleaks/ secret scanPRIVACY_NOTICE.txtTERMS_AND_CONDITIONS.txtin the Legal PR diff/privacy/privacyoncl8y.commay still 404 per #12 until 301 is enabledLegal portal Playwright: existing
web/e2eplus new privacy spec, 5 workers.Test plan (attack, hack, and abuse)
build_acceptance_messagePOST /update_termspublishes the privacy file/privacy?redirect=https://phish.example/javascript:///evilLocationfrom query on footer click<script>, markdown HTML)innerHTML/privacyADMIN_TOKEN, bot tokens, or live Telegram user idssigned_latestused as Privacy consent*so anyone can POST a fake privacy document/privacyon marketingwindow.location.hostname + "/privacy"terms.cl8y.com/traders/{addr}is public/privacy. Portal/marketingframe-ancestors/ clickjacking headers stay on their own issuesVerification criteria
PRIVACY_NOTICE.txtin this repo; counsel approval recorded on the PR (not in a public paste of email).webe2e, 5 workers)./privacyis the notice; sign routes still T&Cs.TERMS_AND_CONDITIONS.txtdiff empty; message unit tests green; a previously valid T&Cs signature still verifies.href="https://terms.cl8y.com/privacy"on all four hosts (portal may use same-origin/privacythat is that document).api/src/message.rs/ clickwrapmessage.ts. NoTermsGateadded to CL8Y-web.yarn test && yarn typecheck && yarn test:e2e --workers=5; DEX frontend tests for the legal footer; bridge e2e clickwrap + footer.+1on CL8Y-web#12 with the canonical URL after prod/preview serve works. #12, #34, #165 remain open until their own AC lands.Out of scope
path="*").bridge.cl8y.comproperty ops (#34, bridge#134).content_sha256oracle (#6).vote.cl8y.com) unless a follow-up issue adds that row.References
TERMS_AND_CONDITIONS.txt(Version: 1.5)packages/cl8y-clickwrap/src/react/TermsGate.tsxapi/src/routes/signatures.rsweb/src/main.tshttps://terms.cl8y.com·https://api.terms.cl8y.comConfirmed the notice URL should be https://terms.cl8y.com/privacy (not the T&Cs home)
cl8y-pm S1 opt-out card completed: required. Product events stay blocked until an opt-out exists. Privacy Notice unlock card was already done; this issue remains the notice + terms.cl8y.com/privacy work.
Live URL check from cl8y-pm ops 2026-09-09. No secret values.
Operator completed a phone card to confirm
https://terms.cl8y.com/privacyand wrote approve, while noting the page still looks like the T&Cs acceptance portal (property query copy).Independent GET of
/privacyand/both 200 with titleCL8Y Legal — Terms & Conditions. No Privacy Notice document at that path yet./privacystill falls through to T&Cs home.Unlock-to-publish is not clean until this route serves a dedicated notice.