Files
podcastdistributiona/app/(marketing)/acceptable-use/page.tsx
T
Leon SerfatyandClaude Opus 5 3e9ba07175 feat: Cloudflare Turnstile on auth, CSP fixes, admin/SEO/analytics additions
Turnstile bot protection (sign-in, sign-up, password-reset):
- Register Better Auth's captcha plugin with the cloudflare-turnstile
  provider; endpoints listed explicitly rather than relying on defaults.
  /reset-password is intentionally excluded — it is reached only via a
  single-use emailed token.
- Add an explicit-render Turnstile widget component. Tokens are single-use,
  so each form resets the challenge after a failed submit; submit stays
  disabled until a token is held.
- Read the site key server-side and pass it down as a prop, so rotating it
  does not require a rebuild.
- Fail fast in production when TURNSTILE_SECRET_KEY is missing, and when a
  secret is set without a site key (that combination would demand a token
  no form can produce, locking every user out).
- Pass a throwaway secret during `next build` in the Dockerfile, mirroring
  the existing BETTER_AUTH_SECRET treatment, so image builds don't need it.

CSP fixes in middleware (these blocked Turnstile entirely):
- Add frame-src for challenges.cloudflare.com. Without it the widget's
  iframe fell back to default-src 'self' and was blocked outright.
- Allow 'unsafe-eval' and websockets in DEVELOPMENT only. `next dev`
  compiles with eval(), so the strict policy threw EvalError and killed
  hydration — no client JS ran at all, which also meant form submit
  handlers never fired. Production policy is unchanged and still strict.

Also included (concurrent work in the tree):
- Admin organizations pages and lib/admin/orgs.
- Episode moderation migration, SEO metadata (sitemap, robots, JSON-LD,
  OG/Twitter images, manifest), Umami analytics, not-found page.

Local dev database: docker-compose.dev.yml provisions Postgres 18 on port
5443 (5432-5442 are in use by other local projects).

Note: `npx tsc --noEmit` currently fails in app/(app)/team/page.tsx — an
`invitations` prop the component does not accept. This predates the commit
and will fail `next build` until fixed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 11:10:55 -04:00

78 lines
3.4 KiB
TypeScript

import type { Metadata } from "next";
import { LegalDoc, type LegalSection } from "@/components/marketing/legal-doc";
import { pageMetadata } from "@/lib/seo";
/** Shared by the page metadata and the document's structured data. */
const PATH = "/acceptable-use";
const DESCRIPTION =
"What you may and may not create with Podcast Distribution AI — prohibited content, voice and likeness rules, rate limits, and how we enforce them.";
export const metadata: Metadata = pageMetadata({
title: "Acceptable Use Policy",
description: DESCRIPTION,
path: PATH,
});
const UPDATED = "June 7, 2026";
const SECTIONS: LegalSection[] = [
{
heading: "Purpose",
paragraphs: [
"This Acceptable Use Policy (AUP) sets out what you may and may not do with Podcast Distribution AI. It supplements our Terms of Service. We may update it as the service and abuse patterns evolve.",
],
},
{
heading: "Prohibited content",
paragraphs: ["You may not use Podcast Distribution AI to create, store, or distribute content that:"],
bullets: [
"Is illegal, infringes intellectual-property or privacy rights, or violates any applicable law.",
"Is hateful, harassing, threatening, or incites violence against people or groups.",
"Is sexually explicit, exploits minors, or sexualizes real individuals.",
"Impersonates a real person or clones a real voice or likeness without that person's consent.",
"Spreads deliberate disinformation, fraud, or scams, or facilitates malware or phishing.",
],
},
{
heading: "Prohibited conduct",
paragraphs: ["You also agree not to:"],
bullets: [
"Bypass or attempt to bypass usage limits, rate limits, authentication, or other security controls.",
"Scrape, reverse-engineer, or attempt to extract the underlying models or source code.",
"Resell, sublicense, or white-label the service except as expressly permitted by your plan.",
"Use automated access (including the API) in a way that degrades the service for others.",
],
},
{
heading: "AI-generated media",
paragraphs: [
"Because Podcast Distribution AI produces synthetic voice and imagery, you are responsible for using it ethically: do not create deceptive deepfakes of real people, and disclose that audio is AI-generated where your audience or the law expects it. You are responsible for clearing any rights needed for the topics, names, and references in your episodes.",
],
},
{
heading: "Enforcement",
paragraphs: [
"We use automated moderation to screen topics and generated scripts, and we may flag, hold, remove, or refuse to generate content that violates this policy. We may suspend or terminate accounts that abuse the service or put it, our providers, or other users at risk — immediately in serious cases.",
],
},
{
heading: "Reporting abuse",
paragraphs: [
"If you believe content created with Podcast Distribution AI violates this policy, report it to abuse@podcastdistributionai.com with enough detail for us to investigate.",
],
},
];
export default function AcceptableUsePage() {
return (
<LegalDoc
title="Acceptable Use Policy"
updated={UPDATED}
intro="We want Podcast Distribution AI to be a safe, trustworthy place to create. This policy describes the content and conduct that are not allowed on the platform."
sections={SECTIONS}
path={PATH}
description={DESCRIPTION}
/>
);
}