feat(frontend): add CL8Y Legal clickwrap (Terra Classic TermsGate) #12
Labels
No labels
bug
docs
documentation
duplicate
enhancement
frontend
good first issue
help wanted
invalid
missing-implementation
priority
medium
product
QA
question
testing
UX
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/ustr-cmm#12
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
Integrate
@plasticdigits/cl8y-clickwrapfrom cl8y-ecosystem-legal so connected Terra Classic wallets must accept the latest CL8Y ecosystem Terms & Conditions for this site’s property before swap / referral-register (and any other wallet execute). Signing happens on the hosted portal (https://terms.cl8y.com); this app only checks status and redirects.Reference implementation (do not copy DEX-only files blindly): cl8y-dex-terraclassic#517 +
ConnectedTermsGate/legalClickwrap.ts/skills/AGENTS_FRONTEND_CLICKWRAP.md.Current codebase
frontend/src/App.tsx,components/layout/Layout.tsxHeader+<main>{children}</main>+Footer. No terms gate, no first-visit NFA modal.hooks/useWallet.ts,stores/wallet.ts,WalletButton.tsxaddressisterra1…oncolumbus-5. Connect does not check Legal.hooks/useSwap.ts→contractService.executeSwapconnectedis the only wallet gate. CTA: connect or swap.pages/ReferralPage.tsx→registerReferralCodecomponents/layout/Footer.tsxfrontend/package.json@plasticdigits/cl8y-clickwrap. No.npmrcfor the GitLab npm registry.frontend/vite.config.tsconnect-srchelper (unlike DEXviteCsp.ts).frontend/frontend/index.htmlog:urlhttps://ust1cmm.comhttps://api.terms.cl8y.com. Signing oncl8y.comdoes not satisfyust1cmm.com.TermsGatefrom the SDK hides children whenaccountis empty (rendersfallback). Wrapping the wholeLayoutwithout a disconnected passthrough would blank Home/Treasury for anonymous users.Why this is needed
cl8y.comordex.cl8y.comis not evidence forust1cmm.com.Content-SHA256message binding, and Terra Classic verify. Reimplementing ADR-036 orsubmitWallethere would diverge and is out of scope.SwaporregisterReferralCodewith no Legal record.Constraints / guardrails
@plasticdigits/cl8y-clickwrap(createClient,TermsGate/useSignatureStatus,sanitizeRedirectUri). Do not implement Terra Classic ADR-036 verify or POST/signatures/walletin this repo.ust1cmm.com(browser Origin). Override only viaVITE_LEGAL_PROPERTYfor staging. Never querycl8y.com/dex.cl8y.comby accident.network="TerraClassic"→ APITERRA_CLASSIC. Never EVM / Solana / Telegram on this dapp.TermsGateas the app root.signed_latest !== true, do not render swap/register execute paths (or the gated<main>). API outage ≠ signed. Do not treat localStorage as proof.redirect_uri(sanitizeRedirectUri+ allowlist includinghttps://ust1cmm.com). PortalVITE_REDIRECT_URI_ALLOWLISTremains authoritative. Prod builds must not sendlocalhostredirect URIs.sign_urls.terra_classic. Do not embed the portal.terms/latest+signatures/statusonly.signed_latestforever in localStorage. Rely on SDK status + window-focus re-poll. Terms version bumps must re-gate.pollIntervalMstight loop (default focus-only is enough). Do not hammerapi.terms.cl8y.com.VITE_PLAYWRIGHT_E2E=truemay skip the gate for automation only. Must be unset on production / Coolify / manual QA.Relevant files
This repo (
ustr-cmm)frontend/src/App.tsx,frontend/src/components/layout/Layout.tsx,Header.tsx,Footer.tsxfrontend/src/hooks/useWallet.ts,stores/wallet.ts,components/common/WalletButton.tsxhooks/useSwap.ts,components/swap/SwapCard.tsx,pages/ReferralPage.tsx,services/contract.ts(executeSwap,registerReferralCode)frontend/package.json, newfrontend/.npmrc,frontend/src/vite-env.d.tsfrontend/src/utils/legalClickwrap.ts,frontend/src/components/legal/ConnectedTermsGate.tsxLegal platform (ops / cross-repo)
@plasticdigits/cl8y-clickwrap— GitLab npm project 82547916 (@plasticdigits:registry=https://gitlab.com/api/v4/projects/82547916/packages/npm/)https://api.terms.cl8y.com—GET /api/v1/terms/latest,GET /api/v1/signatures/statushttps://terms.cl8y.com/sign/terra-classic?property=ust1cmm.compackages/cl8y-clickwrap/README.md;skills/portal-sign-disclosure,skills/terra-classic-adr036,skills/security-opsCORS_ORIGINS; portal redirect allowlistRecommended direction
Mirror the DEX shell gate, adapted to this Layout (no
#138risk modal here).frontend/.npmrcscoping@plasticdigitsto GitLab project82547916.cd frontend && npm install @plasticdigits/cl8y-clickwrap.legalClickwrap.ts: singletoncreateClient(),DEFAULT_LEGAL_PROPERTY = 'ust1cmm.com',LEGAL_REDIRECT_ALLOWLIST = ['https://ust1cmm.com'],resolveLegalRedirectUri(), optionalVITE_LEGAL_*overrides,skipLegalClickwrapForAutomation().ConnectedTermsGate: if noaddress(or automation skip) →children. Else wrapTermsGatewithnetwork="TerraClassic",appName="USTR CMM", sanitizedredirectUri, styledfallback/unsigned.{children}insideLayout<main>(or equivalent) so Header/Footer/WalletButton stay up. Do not gate the whole page chrome.https://terms.cl8y.comorGET …/terms/latest/content?property=ust1cmm.com(new tab,noopener noreferrer).https://ust1cmm.comto Legal APICORS_ORIGINSand portalVITE_REDIRECT_URI_ALLOWLIST; redeploy Legal API + web.handleAccept).useSwap/registerReferralCodealso no-op unlesssigned_latest(shell gate is primary).Acceptance criteria
@plasticdigits/cl8y-clickwrapinstalled via GitLab npm; no forked Terra verify / wallet submit in this repo.ust1cmm.comused on every status + sign URL; registered on Legal admin.signed_latest: false(or stale version): styled accept UI; Swap Now / register-code cannot fire; Header disconnect still works.signed_latest: true: existing swap/referral UX unchanged./sign/terra-classic?property=ust1cmm.comwith allowlistedredirect_uri+appName.CORS_ORIGINS+ portal redirect allowlist includehttps://ust1cmm.com.ADMIN_TOKEN, no localhost redirect in prod bundles, nosigned_latestdurable localStorage cache.Test plan (all paths)
Disconnected / browse
Connect + unsigned
terra1…→ oneGET /signatures/status?property=ust1cmm.com&network=TERRA_CLASSIC&account=….terms.cl8y.com/sign/terra-classic?property=ust1cmm.com&redirect_uri=https%3A%2F%2Fust1cmm.com%2F….Connect + signed
signed_latest: true→ children immediately; swap/register work as today.signed_version).Return from portal
redirect_urireturns to the same path (e.g./or/referral)./swap/:codestill in the URL / storage after round-trip.Failure / env
ust1cmm.com→ fail-closed (document ops fix).VITE_LEGAL_PROPERTYstaging override does not leak into the production default.resolveLegalRedirectUrirejectshttp://localhost:5173.PROD(and only if portalVITE_ALLOW_LOCALHOST_REDIRECTis on for that env).Ops
register-property.sh ust1cmm.comlisted;GET /api/v1/terms/latest?property=ust1cmm.comreturnssign_urls.terra_classic.Test plan (attack, hack, abuse)
TermsGateon<App>executeSwapnot reachablesigned_latestin localStoragesigned_latestcl8y.com, use this siteust1cmm.comEVM)terra1TerraClassicredirect_uri=https://evil.exampleallowLocalhost: !import.meta.env.PRODwindow.location; no iframesignArbitrary/submitWalletinfrontend/srcexcept SDKhttps://ust1cmm.comonlypollIntervalMsunless ≥ focus-only; reuse singleton clientinnerHTMLtermssigned_latest: trueapiBaseUrlfrom query stringVITE_PLAYWRIGHT_E2E=truebaked into Coolify/swap/codestripped by portal returnredirect_uriis currenthrefincluding pathVerification criteria
https://ust1cmm.comwith a new wallet: connect → accept panel → portal Terra Classic sign → return → one successful statussigned_latest: true→ swap or register works.property=ust1cmm.comandnetwork=TERRA_CLASSIC; no Legal admin routes; no BSC/EVM sign URLs./treasurywith no Legal status request required.https://ust1cmm.com(Coolify Legal API + portal rebuild).ADMIN_TOKENinfrontend/; no custom ADR-036; property default isust1cmm.com.mentioned in commit
737f560578mentioned in merge request !32
Implemented on !32.
Shipped:
@plasticdigits/cl8y-clickwrapvia GitLab npm,ConnectedTermsGatearound Layout<main>(disconnected browse stays open), propertyust1cmm.com/TerraClassic, sanitized redirect allowlist, Footer Terms, fail-closed swap/register. Playbook:skills/frontend-legal-clickwrap/SKILL.md.Not done here (Legal platform ops):
register-property.sh ust1cmm.com, APICORS_ORIGINS, portalVITE_REDIRECT_URI_ALLOWLIST. KeepVITE_PLAYWRIGHT_E2Eunset on ust1cmm.com builds.mentioned in commit
09a54333aa