@plantagoai/legal
Privacy Policy and Terms of Service document generation, user acceptance tracking with version gating, and React components for consent flows.
Consumers: All 5 projects
Installation
"@plantagoai/legal": "file:../../shared/packages/legal"
Exports
| Entry Point | Description |
|---|---|
@plantagoai/legal |
Server: document generation, consent recording/checking |
@plantagoai/legal/react |
Client: React hooks and components for consent UI |
Peer Dependencies
| Dependency | Required For |
|---|---|
firebase-admin |
Consent storage in Firestore |
firebase |
Client-side consent checks |
react |
React hooks and components |
Document Generation
Generate tailored Privacy Policy and Terms of Service based on project configuration. Documents are generated as both Markdown and HTML with a versioned hash.
Privacy Policy
import { generatePrivacyPolicy } from "@plantagoai/legal";
const privacy = generatePrivacyPolicy({
companyName: "Foundation",
companyEntity: "PlantagoAI Ltd",
jurisdiction: "Ireland",
contactEmail: "privacy@plantagoai.com",
dataCollected: ["document_hash", "votes", "wallet_address"],
dataNotCollected: ["name", "date_of_birth", "biometric_raw_data"],
thirdParties: ["Anthropic (AI review)", "Solana (blockchain)"],
hasAI: true,
aiProvider: "Anthropic Claude",
aiPurpose: "Constitutional review of governance proposals",
hasBlockchain: true,
blockchainNetwork: "Solana",
isAlpha: true,
retentionDays: 365,
});
console.log(privacy.markdown); // Full privacy policy in Markdown
console.log(privacy.html); // HTML version
console.log(privacy.version); // "2026-04-16"
console.log(privacy.hash); // SHA-256 content hash
Terms of Service
import { generateToS } from "@plantagoai/legal";
const tos = generateToS({
companyName: "MarketHub",
companyEntity: "PlantagoAI Ltd",
jurisdiction: "Ireland",
contactEmail: "legal@markethub.com",
dataCollected: ["name", "email", "purchase_history"],
hasPayments: true,
paymentProvider: "Braintree",
hasAI: true,
aiProvider: "Anthropic Claude",
aiPurpose: "Product descriptions and recommendations",
hasMedicalContent: false,
});
Template Sections
Documents are assembled from modular sections based on the config:
| Section | Included When |
|---|---|
| Data Collection | Always |
| Data Not Collected | dataNotCollected provided |
| AI Usage Disclosure | hasAI: true |
| Medical Disclaimer | hasMedicalContent: true |
| Blockchain Data | hasBlockchain: true |
| Payment Terms | hasPayments: true |
| Alpha/Beta Notice | isAlpha: true |
| Third-Party Services | thirdParties provided |
ProjectLegalConfig
| Field | Type | Required | Description |
|---|---|---|---|
companyName |
string |
Yes | Display name |
companyEntity |
string |
No | Legal entity name |
jurisdiction |
string |
No | Legal jurisdiction |
contactEmail |
string |
Yes | Contact email for legal inquiries |
dataCollected |
string[] |
Yes | Types of data collected |
dataNotCollected |
string[] |
No | Explicitly not collected (privacy emphasis) |
thirdParties |
string[] |
No | Third-party services with data access |
hasAI |
boolean |
No | Uses AI features |
aiProvider |
string |
No | AI provider name |
aiPurpose |
string |
No | What AI is used for |
hasMedicalContent |
boolean |
No | Includes medical/health content |
hasPayments |
boolean |
No | Processes payments |
paymentProvider |
string |
No | Payment processor name |
hasBlockchain |
boolean |
No | Uses blockchain |
blockchainNetwork |
string |
No | Blockchain network name |
isAlpha |
boolean |
No | Alpha/beta stage |
retentionDays |
number |
No | Data retention period |
LegalDocument
interface LegalDocument {
markdown: string; // Full document in Markdown
html: string; // Full document in HTML
version: string; // Version date string
hash: string; // SHA-256 of content
}
Acceptance Tracking (Server)
Record and verify user consent in Firestore. Stored in the legal_consents collection.
Record Consent
import { recordConsent } from "@plantagoai/legal";
await recordConsent("user-123", "tos", "2026-04-16", "org-1");
await recordConsent("user-123", "privacy", "2026-04-16", "org-1");
Check Consent
import { checkConsent } from "@plantagoai/legal";
const accepted = await checkConsent("user-123", "tos", "2026-04-16");
if (!accepted) {
// Show ToS acceptance gate
}
Get History
import { getConsentHistory } from "@plantagoai/legal";
const history = await getConsentHistory("user-123");
// [
// { userId: "user-123", docType: "tos", version: "2026-04-16", tenantId: "org-1", timestamp: Date },
// { userId: "user-123", docType: "privacy", version: "2026-04-16", tenantId: "org-1", timestamp: Date },
// ]
React Components (Client)
TosGate
Wraps your app — blocks access until the user accepts the current ToS version:
import { TosGate } from "@plantagoai/legal/react";
function App() {
return (
<TosGate tosContent={tosMarkdown} version="2026-04-16">
<MainApp />
</TosGate>
);
}
The gate:
- Checks if the current user has accepted this version
- If not, shows the ToS with an Accept button
- On acceptance, records consent via
recordConsent - Renders children once accepted
useTosAccepted
Hook for custom consent UI:
import { useTosAccepted } from "@plantagoai/legal/react";
function CustomGate() {
const { accepted, loading, accept } = useTosAccepted("tos", "2026-04-16");
if (loading) return <Spinner />;
if (!accepted) return <TosModal onAccept={accept} />;
return <App />;
}
Per-Project Configuration
| Project | Data Profile | Special Sections |
|---|---|---|
| Foundation | Zero-PII (hashes, votes, wallet) | Blockchain, AI, Alpha |
| MarketHub | E-commerce (name, email, purchases) | Payments, AI |
| HerbPulse | Medical (symptoms, preferences) | Medical disclaimer, AI |
| Nomadex | Travel (location, preferences) | Subscription, AI |
| Soho | Business (contacts, invoices) | — |