You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Visitors can read the real event description at the canonical internal detail page and start registration at the canonical internal registration page. No public page, metadata, feed, or structured data sends a visitor to Luma. Luma is a reviewed one-time migration source only; it is never a runtime dependency or a second event system.
This is the smallest P0 content-and-integration slice. It does not create the Event model or registration lifecycle and it does not redesign the event surfaces.
Reconcile normative email specifications to Relay ownership #124 is already satisfied and remains the Relay boundary. The website creates the business state, one logical EmailDelivery, and one durable job atomically; only the leased after-commit job calls Relay.
#112 is an independent, already-present aggregate-only overlay and must remain unchanged. #130 owns event/homepage visual composition and CSS; #127 owns migrated body content, link/CTA behavior, and integration with the registration form. Neither issue depends logically on the other, but the second implementation must rebase on the first accepted template work rather than overwrite it.
Source baseline
The reviewed local source is /home/alexey/tmp/luma-exporter/luma-events from exporter commit a0ede3c1451d34c5bc99acf58459ef1c65ae51df:
168 checkpoint JSON files and 168 matching, non-empty Markdown descriptions;
These digests cover only the reviewed public-safe projection, never checkpoint guest arrays or CSV identity data. The source directory is local operator input; it is not copied wholesale, committed, read during requests/builds, or contacted over the network.
The reviewed Luma snapshot owns candidate Markdown description content and migration provenance only. It may suggest source registration state but cannot silently replace canonical identity, lifecycle, title, or time.
Produce a deterministic review manifest that classifies every snapshot event as match, create, or exclude, names the canonical Event slug for every match/create, and records a bounded reason. Exact normalized source URL/ID or exact title plus instant may generate a candidate; fuzzy matching never writes or activates data. Every candidate is reviewed.
Source-only current events cannot be silently dropped. They are created only from the strict public allowlist after review, with a stable non-colliding slug, or excluded with an explicit reason. Existing projection-only events remain valid. In particular, do not invent a body or relationship for a projection event absent from the source.
Conflicting title, time, slug, duplicate mapping, or one source event targeting multiple canonical events fails the candidate run for review. No last-write-wins behavior is allowed.
After activation, the database Event and the shared Implement the event lifecycle, public pages, people, and calendar contracts #45 application services are authoritative. Studio and the admin API edit the same revisioned content. A future exporter snapshot creates another dry-run/review candidate; it never overwrites operator edits automatically.
Public-safe import boundary
Add a network-free, explicitly invoked, idempotent migration command using the project uv workflow. It must support dry-run/report and explicit apply, validate the source baseline/schema, preflight the complete candidate, and apply atomically through #45 services. A failed or stale run changes nothing. Reapplying the same reviewed candidate is a no-op; rollback uses the project revision/activation mechanism rather than deleting history.
Only allowlisted public event fields and the matching Markdown description may cross the boundary. Raw checkpoint files, guests, attendee/guest CSVs, names/emails/answers, meeting or join URLs, access codes, private organizer/contact fields, API data, tokens, filenames/paths tied to attendee evidence, and whole-checkpoint hashes must never enter repository fixtures, database rows, reports, logs, metrics, screenshots, or rendered output. Public speaker identities already approved by the canonical Event record are unaffected; source text that appears to contain a private identity or access secret fails review rather than being guessed safe.
The command must reject unreadable/missing input, unexpected schema, invalid UTF-8, oversized content, duplicate basenames/IDs, traversal or symlink escape, unsafe fields, and partial description/checkpoint sets with a bounded non-sensitive error.
Markdown and link policy
Parse Markdown through the project's allowlisted sanitizer. Raw HTML, unsafe schemes/attributes, scripts, embeds, forms, tracking pixels, and unsafe remote images fail or are removed according to one tested policy; no source HTML is trusted.
Rewrite known datatalks.club links to exact canonical routes. Rewrite courses.datatalks.club only through an explicit accepted compatibility map. A missing or ambiguous internal target blocks activation rather than producing a broken link.
Classify every luma.com/lu.ma destination. A mapped event-detail link becomes /events/<slug>; a mapped registration-intent link becomes /events/<slug>/register; obsolete/unmapped Luma links are explicitly removed or block review. No Luma URL survives in rendered HTML, attributes, metadata, JSON-LD, feeds, sitemap material, or stored public content.
Do not hotlink Luma CDN assets. A reviewed image is imported as a checksum-addressed local asset with required accessible metadata, or omitted with a visible review warning.
Preserve safe, useful non-registration destinations such as recordings. This issue does not broadly migrate or reclassify historical Eventbrite data, but no external destination may be selected as the current primary registration CTA.
Closed, completed, cancelled, unpublished, or otherwise unavailable events show the truthful lifecycle state and no active registration CTA. Existing useful recording actions remain clearly labelled.
/events/<slug>/register and its form behavior, privacy copy, uniform responses, verification/cancellation, abuse controls, and trailing-slash compatibility are exactly those accepted in Implement accountless verified event registration and cancellation #46. This issue consumes that service and must not duplicate it.
Canonicals, robots, metadata, sitemap inclusion, caching, and query handling follow the route registry. Registration pages/outcomes are private, no-store, and non-indexable.
Studio and admin API parity
Imported description, lifecycle-derived availability, source mapping summary, and revision state are managed through #45's shared services. Studio and the admin API expose equivalent authorized operations, validation, optimistic conflict behavior, audit events, and safe errors; public views are read-only consumers. Provenance is management-only and redacted. Raw source payloads and attendee data are never returned.
Registration record operations, exports, attendance, bulk messaging, and provider diagnostics remain owned by #46/#47/#49 and are not added here.
Acceptance criteria
A dry run classifies all 168 source event/description pairs and every source-only current event; every row has one reviewed match, create, or exclude decision and no fuzzy or unclassified write path.
Apply is all-or-nothing, repeatable, and network-free. Missing/stale/malformed/unsafe source, mapping conflicts, and invalid links produce bounded errors with no writes or private data disclosure.
Only public-safe allowlisted values enter Event revisions. Automated canary tests prove guest/CSV/private checkpoint values cannot cross into fixtures, storage, logs, reports, APIs, pages, or screenshots.
Every activated matched/created Event renders its reviewed sanitized description at /events/<slug>; an unmatched or intentionally empty Event renders the accepted fallback without fabricated content.
The public crawl and stored activated body/link fields contain zero luma.com, lu.ma, Luma CTA, or Luma CDN destination. Known internal links resolve directly to canonical paths; useful recording links still work.
Every eligible event's sole primary registration CTA targets /events/<slug>/register; unavailable events expose no actionable registration CTA and accurately state why.
Studio and admin API edits affect the same canonical Event revision and public view, have permission/parity/conflict/audit tests, and never expose raw migration or attendee data.
Full Django/unit/integration/link/security tests pass via uv-backed commands, with no unexplained route, canonical, metadata, cache, sitemap, accessibility, or existing recording-link regression.
Browser acceptance scenarios
Verify at web.dtcdev.click at desktop (1440px) and mobile (390px), in light and dark modes where #130 supplies them. Screenshots must use synthetic addresses and contain no source/private registration data.
Upcoming eligible event: enter from homepage and /events; both link to the internal detail. Confirm meaningful description hierarchy, safe links, exact canonical, internal Register CTA, readable form, keyboard focus, labels/errors, and the uniform submitted state.
Completed event with recording: confirm description and recording remain usable, state is truthful, and there is no registration CTA.
Cancelled/closed/unpublished/missing event: confirm the accepted closed state or non-enumerating 404, no stale CTA, no private cacheability, and no existence/registration leak.
No source description: confirm the compact fallback and absence of invented content.
Link edge cases: confirm an old internal URL reaches the exact canonical directly, a mapped Luma registration link is internal, unsafe/unknown links cannot activate, and the rendered DOM/source has no Luma URL.
Registration failures: invalid input, duplicate submit, throttling, Relay unavailable, and verification/cancellation link edge cases retain Implement accountless verified event registration and cancellation #46's accessible, enumeration-resistant, no-store behavior and do not lose committed business state.
Management parity: with authorized and unauthorized staff roles, edit/publish/revert the description through Studio and the API and confirm equivalent validation, conflict, audit, denial, and public activation behavior.
Outcome
Visitors can read the real event description at the canonical internal detail page and start registration at the canonical internal registration page. No public page, metadata, feed, or structured data sends a visitor to Luma. Luma is a reviewed one-time migration source only; it is never a runtime dependency or a second event system.
This is the smallest P0 content-and-integration slice. It does not create the Event model or registration lifecycle and it does not redesign the event surfaces.
Normative contracts
_docs/specs/02-url-link-seo-compatibility.md_docs/specs/05-events-registration-email.md_docs/specs/06-studio-and-admin-api.md_docs/specs/07-security-privacy-operations.md_docs/specs/09-migration-rollout-roadmap.md_docs/specs/10-verification-strategy.mdIf this issue and a normative specification differ, the specification wins unless the owner approves a decision change.
Required dependencies and gates
Blocked: do not implement or activate this issue yet.
/events/<slug>/registerroute and accountless verified-registration service. Its dependencies, including Decision: Confirm verified-email registration semantics #17 and Build the durable Relay delivery intent and status lifecycle #49, remain owned there.EmailDelivery, and one durable job atomically; only the leased after-commit job calls Relay.#112 is an independent, already-present aggregate-only overlay and must remain unchanged. #130 owns event/homepage visual composition and CSS; #127 owns migrated body content, link/CTA behavior, and integration with the registration form. Neither issue depends logically on the other, but the second implementation must rebase on the first accepted template work rather than overwrite it.
Source baseline
The reviewed local source is
/home/alexey/tmp/luma-exporter/luma-eventsfrom exporter commita0ede3c1451d34c5bc99acf58459ef1c65ae51df:b2859a7be33fb29821d53e25265ce91c37f376f1de7467780a351d707294fbc5;6ffd000db03b71c7308d83328a5d744ccec298b1cca458aa04831689431b030a.These digests cover only the reviewed public-safe projection, never checkpoint guest arrays or CSV identity data. The source directory is local operator input; it is not copied wholesale, committed, read during requests/builds, or contacted over the network.
Source precedence and reconciliation
match,create, orexclude, names the canonical Event slug for every match/create, and records a bounded reason. Exact normalized source URL/ID or exact title plus instant may generate a candidate; fuzzy matching never writes or activates data. Every candidate is reviewed.Public-safe import boundary
Add a network-free, explicitly invoked, idempotent migration command using the project
uvworkflow. It must support dry-run/report and explicit apply, validate the source baseline/schema, preflight the complete candidate, and apply atomically through #45 services. A failed or stale run changes nothing. Reapplying the same reviewed candidate is a no-op; rollback uses the project revision/activation mechanism rather than deleting history.Only allowlisted public event fields and the matching Markdown description may cross the boundary. Raw checkpoint files,
guests, attendee/guest CSVs, names/emails/answers, meeting or join URLs, access codes, private organizer/contact fields, API data, tokens, filenames/paths tied to attendee evidence, and whole-checkpoint hashes must never enter repository fixtures, database rows, reports, logs, metrics, screenshots, or rendered output. Public speaker identities already approved by the canonical Event record are unaffected; source text that appears to contain a private identity or access secret fails review rather than being guessed safe.The command must reject unreadable/missing input, unexpected schema, invalid UTF-8, oversized content, duplicate basenames/IDs, traversal or symlink escape, unsafe fields, and partial description/checkpoint sets with a bounded non-sensitive error.
Markdown and link policy
datatalks.clublinks to exact canonical routes. Rewritecourses.datatalks.clubonly through an explicit accepted compatibility map. A missing or ambiguous internal target blocks activation rather than producing a broken link.luma.com/lu.madestination. A mapped event-detail link becomes/events/<slug>; a mapped registration-intent link becomes/events/<slug>/register; obsolete/unmapped Luma links are explicitly removed or block review. No Luma URL survives in rendered HTML, attributes, metadata, JSON-LD, feeds, sitemap material, or stored public content.Visitor behavior
/events/<slug>remains the no-trailing-slash canonical detail from Implement the event lifecycle, public pages, people, and calendar contracts #45 and renders the sanitized description as meaningful structured content. A missing description has a truthful compact fallback; it never receives invented copy.Registerand links only to/events/<slug>/register./events/<slug>/registerand its form behavior, privacy copy, uniform responses, verification/cancellation, abuse controls, and trailing-slash compatibility are exactly those accepted in Implement accountless verified event registration and cancellation #46. This issue consumes that service and must not duplicate it.404; registration ineligible/missing behavior follows Implement accountless verified event registration and cancellation #46 without leaking event capability or attendee identity. Detail errors and every registration response are non-cacheable where the specifications require it.N registereddisplay remains exclusively governed by Import historical registration totals safely and show aggregate event counts #112.no-store, and non-indexable.Studio and admin API parity
Imported description, lifecycle-derived availability, source mapping summary, and revision state are managed through #45's shared services. Studio and the admin API expose equivalent authorized operations, validation, optimistic conflict behavior, audit events, and safe errors; public views are read-only consumers. Provenance is management-only and redacted. Raw source payloads and attendee data are never returned.
Registration record operations, exports, attendance, bulk messaging, and provider diagnostics remain owned by #46/#47/#49 and are not added here.
Acceptance criteria
match,create, orexcludedecision and no fuzzy or unclassified write path./events/<slug>; an unmatched or intentionally empty Event renders the accepted fallback without fabricated content.luma.com,lu.ma, Luma CTA, or Luma CDN destination. Known internal links resolve directly to canonical paths; useful recording links still work./events/<slug>/register; unavailable events expose no actionable registration CTA and accurately state why.uv-backed commands, with no unexplained route, canonical, metadata, cache, sitemap, accessibility, or existing recording-link regression.Browser acceptance scenarios
Verify at
web.dtcdev.clickat desktop (1440px) and mobile (390px), in light and dark modes where #130 supplies them. Screenshots must use synthetic addresses and contain no source/private registration data./events; both link to the internal detail. Confirm meaningful description hierarchy, safe links, exact canonical, internal Register CTA, readable form, keyboard focus, labels/errors, and the uniform submitted state.404, no stale CTA, no private cacheability, and no existence/registration leak.Non-goals