Legal document changelog
Every version of the published documents, newest first. A user's
accounts.tos_version points at an entry here, so entries are never edited or
removed — only added.
Material changes (anything in Terms §§6, 7, 9, 13, 14, 15, 16; any new
prohibition in the AUP; anything touching arbitration) require advance email
notice and re-acceptance. See assent-and-consent.md alongside this file.
2026-09-20.1 — the films page embeds a YouTube player, effective September 20, 2026
The marketing site gains /films, a page of short films made with Lunar Canoe,
played by YouTube's own embedded player. That is the first time any page on
lunarcanoe.com has loaded anything from a third party, so two documents that
said otherwise had to change before the page could publish.
cookies.mdno longer claims the site makes no third-party requests. The opening line now says the site sets no cookies and that one page — the films page — is the only place anything loads from a third party. A new subsection describes exactly what happens: opening the page requests the player and the thumbnails from Google, so Google receives the visitor's IP address, user agent and the page address, the same as opening the video on YouTube directly. The embed is theyoutube-nocookie.comform, which defers Google's advertising cookies until a video is actually played. We receive nothing back and cannot tell who watched what.- The "no embedded video player" phrase is gone, because there is one now. The rest of that sentence — no tracking pixel, no advertising tag, no session recorder, no third-party font — still holds, on every page including this one, and is now stated that way explicitly.
- The "If this changes" section names the exception. The films page is meant to stay the only one; the commitment to ask before setting anything that needs consent is unchanged.
privacy.mdmatches. The "what we don't do" list and the summary bullet both carry the exception rather than a blanket claim, and "No cookies" is now "No cookies set by us".
⚠️ Open for the reviewing lawyer. An embed that loads on page view, rather
than behind a click, is the case EU/UK consent rules are usually read to reach.
We publish what happens and offer the visitor the choice not to open the page;
whether that is sufficient for EEA/UK visitors, or whether the embed should be
click-to-load, is question 12 of docs/08-legal-review-brief.md. This was an
operator decision taken with that question open.
The Terms of Service and the Acceptable Use Policy are unchanged apart from the
version string and effective date they display, which changes
CURRENT_TERMS_DOCUMENT_HASH.
Not material under the rule at the top of this file: no Terms section
changed, the AUP gains no prohibition, and nothing touches arbitration — so no
advance email notice is required. Bumping CURRENT_TERMS_VERSION still shows
every existing account the blocking re-acceptance dialog once on its next
sign-in.
2026-09-19.1 — the cookie notice describes the session cookie, effective September 19, 2026
Two changes, both in cookies.md, and the first is a correction.
- The application section said "The application sets no cookies either" and
that the sign-in credential is "held in the application in memory for the
session". That stopped being true when hosted sign-in shipped: the
application sets
lunarcanoe_session, aHttpOnly; Secure; SameSite=Laxcookie holding a random token, for 30 days of idle life and 90 days absolute. The section now describes that cookie, states that it is strictly necessary (there is no way to be signed in without it, so there is nothing to consent to), and says what signing out and "sign out everywhere" do. ThelocalStoragetable and the "no analytics in the application" statement are unchanged. - The marketing site now asks the application one question. A landing page
asks whether the browser is already signed in, so a "Start free" button can
read "Go to app" instead. The notice says so, says the answer is a single
yes or no, and says what it does not do: store anything in the browser,
record anything about the visit against the account, or keep a sign-in
alive. The site's own "sets no cookies", "no third party" and "nothing in
localStorageorsessionStorage" statements are unchanged and remain true — the request goes to our own application, and the page writes nothing.
The Terms of Service, the Acceptable Use Policy and the Privacy Policy are
unchanged apart from the version string and effective date they display, which
changes CURRENT_TERMS_DOCUMENT_HASH.
Not material under the rule at the top of this file: no Terms section
changed, the AUP gains no prohibition, and nothing touches arbitration — so no
advance email notice is required. Bumping CURRENT_TERMS_VERSION still shows
every existing account the blocking re-acceptance dialog once on its next
sign-in.
2026-09-17.2 — AUP: connecting an agent, effective September 17, 2026
Users can connect their own AI agent (Claude Code, Codex, claude.ai and
others) to their account over OAuth through the MCP endpoint
(docs/20-agent-mcp.md). The agent can read and edit the user's storyboards
and can stage still and soundtrack requests that the user then generates in
the app.
Changed, in acceptable-use.md only:
- §9 gains a subsection, Connecting an agent. A user may connect an agent or other software through a connection method we offer, such as the MCP endpoint; the user is responsible for everything done through a connection they authorise as if they had done it themselves, including anything the policy prohibits; a connection can be revoked at any time, or we will revoke it on request; and section 10 applies to agent access as it does to the rest of the account, so a restriction or suspension of the account applies to the connection too. The existing §9 line against automated access "beyond what we offer" is unchanged; the MCP endpoint is something we offer.
The Terms of Service and the Privacy Policy are unchanged apart from the
version string they display, which changes CURRENT_TERMS_DOCUMENT_HASH.
Not material under the rule at the top of this file: the AUP gains no new
prohibition, and no Terms section or arbitration text changed, so no advance
email notice is required. Bumping CURRENT_TERMS_VERSION still shows every
existing account the blocking re-acceptance dialog once on its next sign-in.
2026-09-17.1 — fal added as a sub-processor, effective September 17, 2026
Generated soundtracks (docs/19-generated-soundtracks.md) send picture and
prompt text to a new vendor, so the Privacy Policy names it before the feature
is turned on in production.
Changed, all in privacy.md:
- §6 sub-processor table: new row for Features & Labels, Inc. (fal). It
receives a silent 720p render of the scenes the user chooses, the soundtrack
prompt and negative prompt, the seed and the duration, and only when the user
generates a soundtrack. The row states what
provider/fal.rsdoes: every queue submit sendsX-Fal-Store-IO: 0, asking fal not to store the request's input and output data (30 days by default), and the upload and the submit ask fal to delete the uploaded render and the generated file after one hour (MEDIA_EXPIRY_SECS). These are worded as requests, because they are preferences we cannot observe being carried out. The row also states that fal's terms let it use anonymised or aggregated usage data derived from customer input to develop its products and models. - §1: one bullet saying a soundtrack sends a silent render and the prompt to fal.
- §2 Generation records: the soundtrack generation record and what it holds.
- §7: fal says it processes data in the United States and other countries, so US-only processing of a soundtrack request is not promised.
- §8 retention table: soundtrack records are kept with the project, and a row for what we ask fal to keep.
site/src/lib/legal.ts gains falMediaExpiry ("one hour"), which must match
MEDIA_EXPIRY_SECS in server/crates/core/src/provider/fal.rs. The account
data summary's processor entry (portability.rs) uses the same wording.
The Terms of Service and the Acceptable Use Policy are unchanged apart from the
version string they display, which changes CURRENT_TERMS_DOCUMENT_HASH.
Not material under the rule at the top of this file: no Terms section, AUP
prohibition or arbitration text changed, so no advance email notice is
required. Bumping CURRENT_TERMS_VERSION still shows every existing account the
blocking re-acceptance dialog once on its next sign-in.
2026-09-06.1 — first published version, effective September 6, 2026
Published without external legal review, as an explicit operator decision.
The alpha was live — accounts, uploads and payments existed — with no
published terms at all, which was the worse state on every axis. The
arbitration, fee and liability values are standard consumer-SaaS forms
(AAA Consumer Arbitration Rules, a 30-day opt-out, we pay fees beyond a court
filing fee, liability capped at the greater of twelve months' fees or US$100).
A legal review remains planned; its outcome ships as the next version through
the notice and re-acceptance process above. The brief for that review is
docs/08-legal-review-brief.md.
The drafting history below is preserved as written.
Created:
terms.md— Terms of Service, including an arbitration agreement, class-action waiver, jury waiver and opt-out (§15).acceptable-use.md— Acceptable Use Policy, including the likeness and consent rule, the minors rule, the NCII notice-and-removal process, and the moderation-evasion rule.privacy.md— Privacy Policy, written against the code: Vertex AI prompt logging for up to 90 days, Cloudflare R2 and Anthropic as sub-processors, and the deletion/backup posture.cookies.md— Cookie and tracking notice. Short, because there are no cookies and no third-party requests.assent-and-consent.md— specification for signup assent and the per-upload consent affirmation (#38).site/src/lib/legal.ts— theready()/todo()facts module and the token renderer.
Nothing renders yet. Issue #40 owns the routes and the signup acceptance flow; issue #38 owns the upload affirmation.
Fourth pass — the documents render, and payments are real (#40)
The publication surface exists: the site now renders terms.md,
acceptable-use.md, privacy.md and cookies.md at /terms,
/acceptable-use, /privacy and /cookies, and this changelog at
/legal/changelog, with the draft banner while anything is unfilled. Adding
those pages armed the build gate, exactly as designed: the site cannot build
for deployment until every todo() in site/src/lib/legal.ts is filled.
The gate also now checks that each policy names the operator and that no
published policy still carries its in-draft warning prose.
Truth pass against what shipped since the third pass:
- Payments are live (#45,
docs/12-payments.md): Stripe Checkout top-ups, auto-recharge, refunds and receipts.paymentProcessorisready("Stripe, Inc."), Stripe moved from the "planned" sub-processor table to "in use today", the Payments section of the Privacy Policy is in the present tense, and the "not yet operative" callout on Terms §9 is gone. - Transactional email is live (#46,
docs/14-email.md): Resend moved to "in use today" — receipts, deletion notices, expiry warnings, export links, enforcement notices. - The marketing site counts visits with self-hosted, cookieless Umami. The cookie notice claimed "no analytics"; it now describes the counter honestly (no cookies, no cross-site tracking, IP addresses not stored), and the Privacy Policy's "what we don't do" list matches.
changeNoticeDaysisready("30"), the number issue #40 specified.- Links into the repository are gone. A published page cannot link to
README.md,assent-and-consent.mdordocs/…; those references are plain text now, and the renderer throws on any relative link that no published route serves. - Every policy names Magic Ingredient LLC — the AUP and the cookie notice previously never said who "we" are.
Operator decisions recorded 2026-09-06, closing four more todo()s:
minimumAgeisready("18")(issue #40 decision 3): adults only, stated in the Terms and to be enforced at signup.creditExpiryisready("do not expire"): prepaid credits never expire, which is the rule that raises no state gift-card questions.storageLocationisready(…ENAM…): the R2 bucket carries Cloudflare's Eastern North America location hint.euRepresentativepublishes the honest interim position: none designated; we rely on the Article 27(2) GDPR exemption and will appoint a representative — and update the line — before the exemption stops applying. ⚠️ Flagged for the reviewing lawyer (question 6 ofdocs/08-legal-review-brief.md).
The remaining nine values — effectiveDate, documentVersion and the seven
arbitration/liability fields — were filled at publication; see the note at the
top of this entry.
Third pass — deletion and retention exist now (#42, #43, #44)
The second pass removed claims about deletion because the machinery did not exist. It does now, so the claims come back — this time describing what the code does, and still refusing to say the one thing we cannot back up.
- Terms §11 is rewritten as a commitment rather than an apology. Self-serve project deletion with a one-day cancellable window, account closure with seven days, a full data export, and a receipt for every deletion.
- Privacy §8 carries a real retention table and Privacy §9 describes what deletion does: rows deleted outright, objects deleted from R2, the edge cache purged, agent-runtime sessions disposed of, and a receipt shown to the user.
- Four new
ready()values, each matching a row ofretention_policiesin the database rather than a claim about one:deletionGraceDays(1),accountDeletionGraceDays(7),unselectedTakeDays(30) andexportRetentionDays(90).retentionSchedulenow points at the published page instead of admitting there is none. backupRetentionDaysis deliberately stilltodo(). No hosting provider is chosen, so there is no backup policy and no honest number. The gate keeps the documents unpublishable until there is one — which is the right trade, because everything else in the deletion promise is now true and this is the only part that would not be.- Two disclosures added rather than left to be discovered. Files are stored under a hash of their contents, so deleting a file whose exact bytes someone else also holds removes your record and leaves the stored file until the last reference goes; and financial records survive account closure, carrying the provider, model, cost and time of each charge and no prompt, image or video.
- Nothing claims an upload-screening vendor. None is contracted. The code
that would disclose one (
deletion::screening_note) is driven by configuration, so the disclosure appears the day a vendor does and not before — a false "we cannot delete this" being as bad as a false "we deleted it".
Second pass — corrected against the code
An external consistency review found four places where the drafts described a system that had not been built. Fixed by deleting the claim or restating it plainly as planned:
- Deletion. Terms §11 and Privacy §9 no longer promise prompt live/storage deletion, agent-runtime disposal, backup roll-off or account closure. Project deletion hides a project; the files remain. Erasure is an operator acting on an email. What is built — complaint-driven removal — is described exactly.
- Consent and moderation. Removed every claim that upload affirmations are recorded, that face or apparent-minor detection runs, and that anything is automatically blocked on those grounds. None of it exists.
- The complaint process. AUP §4 now describes the shipped intake at
/report— categories, the statutory 48-hour NCII clock, required elements, incomplete notices, receipts, quarantine, the append-only log — and says byte-identical copies, across all accounts, because SHA-256 cannot catch a re-encode or a crop. - Complaint data. New Privacy §5 enumerates what a report stores, including the peppered IP hash and the fact that a complaint can never be edited or deleted.
- DMCA. "Our designated agent is …" is gone, along with the
dmcaAgenttoken. No agent is registered, so there is no § 512(c) safe harbour, and the AUP says so. - Sub-processors are split into "in use today" and "planned".
legal.tsis now a real gate.site/scripts/check-legal.mjsruns asprebuild; the build fails while any value is unfilled or any token unknown. Substituted values are HTML-escaped, so neither areadynor atodovalue can inject markup.- Licence. The Atlassian-derived "isolate from further use until deletion is possible" wording is rewritten in our own words — attribution is not permission. The Common Paper attribution now names the agreement and version.