Skip to content

Commit ec798dd

Browse files
authored
Merge pull request #8 from ThinkfleetAI/fix/white-label-render-and-entity
fix(white-label): render MSA/Terms as HTML + fill entity placeholders
2 parents 6a7c2a6 + 46e87a7 commit ec798dd

3 files changed

Lines changed: 58 additions & 14 deletions

File tree

app/controllers/white_label_controller.rb

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ def render_gate(agreement, error: nil)
6868
be taken to a secure page to add a payment method — no account or login required.</p>
6969
#{err_html}
7070
<h2>Master Services & White-Label / SDK License Agreement (#{agreement.msa_version})</h2>
71-
<pre class="doc">#{ERB::Util.html_escape(msa)}</pre>
71+
<div class="doc">#{markdown_to_html(msa)}</div>
7272
<h2>Acceptable Use & Service Terms (#{agreement.terms_version})</h2>
73-
<pre class="doc">#{ERB::Util.html_escape(terms)}</pre>
73+
<div class="doc">#{markdown_to_html(terms)}</div>
7474
<form method="post" action="/white-label/#{ERB::Util.html_escape(params[:token])}/accept">
7575
<label>Full name<input name="signer_name" required value="#{ERB::Util.html_escape(params[:signer_name].to_s)}"></label>
7676
<label>Title<input name="signer_title" required value="#{ERB::Util.html_escape(params[:signer_title].to_s)}"></label>
@@ -112,6 +112,46 @@ def doc_body(kind, version)
112112
raw.sub(/\A<!--.*?-->\s*/m, "").strip
113113
end
114114

115+
# Minimal Markdown -> HTML for the legal docs (no gem dependency): headings,
116+
# bold, unordered lists, horizontal rules, paragraphs. All content is escaped.
117+
def markdown_to_html(text)
118+
out = +""
119+
@list_open = false
120+
text.each_line do |raw|
121+
line = raw.rstrip
122+
if line.empty?
123+
out << close_md_list
124+
elsif (m = line.match(/\A(\#+)\s+(.*)\z/))
125+
out << close_md_list
126+
level = [m[1].length, 6].min
127+
out << "<h#{level}>#{inline_md(m[2])}</h#{level}>"
128+
elsif (m = line.match(/\A[-*]\s+(.*)\z/))
129+
unless @list_open
130+
out << "<ul>"
131+
@list_open = true
132+
end
133+
out << "<li>#{inline_md(m[1])}</li>"
134+
elsif line.match?(/\A-{3,}\z/)
135+
out << close_md_list << "<hr>"
136+
else
137+
out << close_md_list << "<p>#{inline_md(line)}</p>"
138+
end
139+
end
140+
out << close_md_list
141+
out
142+
end
143+
144+
def close_md_list
145+
return "" unless @list_open
146+
147+
@list_open = false
148+
"</ul>"
149+
end
150+
151+
def inline_md(str)
152+
ERB::Util.html_escape(str).gsub(/\*\*(.+?)\*\*/) { "<strong>#{Regexp.last_match(1)}</strong>" }
153+
end
154+
115155
def layout(inner)
116156
<<~HTML
117157
<!doctype html><html lang="en"><head><meta charset="utf-8">
@@ -122,8 +162,12 @@ def layout(inner)
122162
max-width:760px;margin:0 auto;padding:32px 20px;background:#fafafa}
123163
h1{font-size:26px;margin:0 0 8px} h2{font-size:18px;margin:28px 0 8px}
124164
.lead{color:#444} .err{background:#fde8e8;color:#9b1c1c;padding:10px 14px;border-radius:8px}
125-
pre.doc{white-space:pre-wrap;background:#fff;border:1px solid #e2e2e2;border-radius:10px;
126-
padding:18px;max-height:320px;overflow:auto;font:13px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace}
165+
.doc{background:#fff;border:1px solid #e2e2e2;border-radius:10px;padding:18px 22px;
166+
max-height:360px;overflow:auto}
167+
.doc h1{font-size:20px;margin:0 0 10px} .doc h2{font-size:16px;margin:18px 0 6px}
168+
.doc h3{font-size:14px;margin:14px 0 4px} .doc p{margin:0 0 10px;font-size:14px;color:#333}
169+
.doc ul{margin:0 0 10px 18px;padding:0} .doc li{font-size:14px;color:#333;margin:3px 0}
170+
.doc hr{border:0;border-top:1px solid #eee;margin:14px 0} .doc strong{font-weight:600}
127171
form{background:#fff;border:1px solid #e2e2e2;border-radius:10px;padding:18px;margin-top:24px}
128172
label{display:block;margin:0 0 14px;font-weight:600}
129173
label.check{font-weight:400;display:flex;gap:8px;align-items:flex-start}

config/white_label/msa_v1.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
<!--
22
White-Label / SDK Master Services Agreement
33
version: v1 (the acceptance gate records THIS version string against each signer)
4-
status: DRAFT — must be reviewed by qualified counsel before it is presented to a customer.
5-
Bracketed [LIKE_THIS] tokens are deliberate fill-ins. Do not ship with brackets unresolved.
4+
status: DRAFT — reviewed by qualified counsel still recommended before presenting to a customer.
5+
Entity filled: Thinkfleet AI, LLC (NC) d/b/a Flobyte; governing law North Carolina.
66
-->
77

88
# Master Services & White-Label / SDK License Agreement
99

1010
**Version v1 — Effective on acceptance**
1111

12-
This Master Services & White-Label / SDK License Agreement (the **"Agreement"**) is entered into between **[LEGAL ENTITY NAME], a [STATE/COUNTRY] [entity type]** ("**Flobyte**", "**we**", "**us**") and the entity that accepts this Agreement ("**Customer**", "**you**"). By clicking "I Accept," signing an order, or accessing the Service, the individual accepting represents that they are authorized to bind Customer, and Customer agrees to this Agreement as of that date (the "**Effective Date**").
12+
This Master Services & White-Label / SDK License Agreement (the **"Agreement"**) is entered into between **Thinkfleet AI, LLC, a North Carolina limited liability company doing business as "Flobyte"** ("**Flobyte**", "**we**", "**us**") and the entity that accepts this Agreement ("**Customer**", "**you**"). By clicking "I Accept," signing an order, or accessing the Service, the individual accepting represents that they are authorized to bind Customer, and Customer agrees to this Agreement as of that date (the "**Effective Date**").
1313

1414
## 1. Definitions
1515

@@ -46,9 +46,9 @@ Customer will not, and will not permit any End User to: (a) reverse engineer, de
4646

4747
5.2 **Billing & auto-charge.** Fees are billed in advance each billing period through Flobyte's billing processor. By providing a payment method, Customer authorizes Flobyte and its processor to automatically charge that method for all Fees, including renewals and usage charges, until the Agreement is terminated.
4848

49-
5.3 **Auto-renewal.** Subscriptions renew automatically for successive periods equal to the initial term unless either party gives notice of non-renewal at least [30] days before the end of the then-current period.
49+
5.3 **Auto-renewal.** Subscriptions renew automatically for successive periods equal to the initial term unless either party gives notice of non-renewal at least 30 days before the end of the then-current period.
5050

51-
5.4 **Late payment.** Overdue amounts accrue interest at the lesser of 1.5% per month or the maximum permitted by law. Flobyte may suspend the Service for non-payment after [10] days' notice.
51+
5.4 **Late payment.** Overdue amounts accrue interest at the lesser of 1.5% per month or the maximum permitted by law. Flobyte may suspend the Service for non-payment after 10 days' notice.
5252

5353
5.5 **Taxes.** Fees are exclusive of taxes. Customer is responsible for all taxes other than taxes on Flobyte's net income.
5454

@@ -58,7 +58,7 @@ Customer will not, and will not permit any End User to: (a) reverse engineer, de
5858

5959
6.1 **Term.** This Agreement begins on the Effective Date and continues for the subscription term in the Order, renewing under Section 5.3.
6060

61-
6.2 **Termination for cause.** Either party may terminate for the other's material breach not cured within [30] days of notice (or immediately for breach of Sections 3, 4, 7, or 8).
61+
6.2 **Termination for cause.** Either party may terminate for the other's material breach not cured within 30 days of notice (or immediately for breach of Sections 3, 4, 7, or 8).
6262

6363
6.3 **Effect.** On termination, all licenses and White-Label Rights end, Customer ceases use of the Service and SDK, and any accrued Fees become due. Sections that by their nature survive (including 4, 7–12) survive termination.
6464

@@ -80,7 +80,7 @@ Each party will protect the other's Confidential Information with at least reaso
8080

8181
9.1 Flobyte will maintain commercially reasonable administrative, technical, and organizational safeguards designed to protect Customer Data.
8282

83-
9.2 To the extent Flobyte processes personal data on Customer's behalf, the parties will comply with the Data Processing Addendum at **[DPA URL]**, which is incorporated by reference.
83+
9.2 To the extent Flobyte processes personal data on Customer's behalf, the parties will comply with Flobyte's Data Processing Addendum, which Flobyte will make available upon request and which is incorporated by reference.
8484

8585
9.3 Customer is responsible for the legality of Customer Data and for obtaining all consents required from its End Users.
8686

@@ -114,11 +114,11 @@ Customer will comply with all applicable laws, including export controls, sancti
114114

115115
14.2 **Assignment.** Neither party may assign this Agreement without the other's consent, except to a successor in a merger or sale of substantially all assets, with notice.
116116

117-
14.3 **Governing law; venue.** This Agreement is governed by the laws of the State of **[HOME_STATE]**, USA, without regard to conflicts rules. The parties submit to the exclusive jurisdiction of the state and federal courts located in **[HOME_STATE_COUNTY/CITY], [HOME_STATE]**.
117+
14.3 **Governing law; venue.** This Agreement is governed by the laws of the State of **North Carolina**, USA, without regard to conflicts rules. The parties submit to the exclusive jurisdiction of the state and federal courts of competent jurisdiction located in the State of North Carolina.
118118

119119
14.4 **Force majeure.** Neither party is liable for delays caused by events beyond its reasonable control.
120120

121-
14.5 **Notices.** Notices must be in writing to the parties' designated contacts (email permitted for routine notices; legal notices to **[NOTICE ADDRESS]**).
121+
14.5 **Notices.** Notices must be in writing to the parties' designated contacts (email permitted for routine notices; legal notices to Flobyte at its registered business address or the email address Flobyte designates for legal notices).
122122

123123
14.6 **Entire agreement.** This Agreement and the Order are the entire agreement and supersede prior understandings. Any conflicting terms in Customer's purchase documents are rejected. Flobyte may update the Terms and the standard form of this Agreement prospectively for renewals.
124124

config/white_label/terms_v1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Flobyte may suspend or limit the Service, in whole or part, to protect the Servi
5959

6060
## 7. Changes to These Terms
6161

62-
Flobyte may update these Terms prospectively. Material changes take effect at the next renewal or upon [30] days' notice. Continued use after the effective date constitutes acceptance.
62+
Flobyte may update these Terms prospectively. Material changes take effect at the next renewal or upon 30 days' notice. Continued use after the effective date constitutes acceptance.
6363

6464
---
6565

0 commit comments

Comments
 (0)