DataTalksClub / DataTalksClub/website
Manage Relay-owned versioned transactional templates in Studio
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Parent epic: #21.
Accepted policy/specification inputs: #22, #23, and #124.
Normative authority:
_docs/specs/05-events-registration-email.md, especially Relay-owned email templates, Durable delivery model, and Relay sender and provider boundary;_docs/specs/06-studio-and-admin-api.md, especially capability-based roles, Studio Email, and admin API parity;_docs/specs/07-security-privacy-operations.md, for protected values, no-store responses, redaction, audit, and credential boundaries;_docs/specs/09-migration-rollout-roadmap.md, Milestone 6;_docs/specs/10-verification-strategy.md; and_docs/PROCESS.md.
PM disposition
GROOMED / P0 / DEPENDENCY-BLOCKED. Do not dispatch a website #48 engineer lane yet.
#48 owns the website management adapter for Relay-owned transactional templates. Relay remains the sole canonical template catalog, draft/version store, validator, renderer, sender-policy owner, and owner of the rendered transport snapshot. The website owns capability-checked Studio/admin-API orchestration, safe typed purpose/context definitions, redacted audit, and fail-closed consumer-contract behavior. It must not create a second template store, renderer, provider path, or mutable fallback.
No issue body, accepted source commit, local test, Relay deployment, credential, or development rehearsal grants permission to access protected state or send email. The separately controlled development sender ID courses remains allowlisted/simulated except for the one-recipient canary owned by #50's HUMAN gate under explicit operator authority. #48 does not run or authorize that canary.
Outcome
Provide equivalent Studio and /api/v1/admin/ workflows for Relay template catalog/read, one editable draft, safe preview/dry-run, publish, historical republish, and test-send preparation against an immutable template key/version.
An actual email-generating test send is a durable delivery, not a template-management side effect. It must use #49's accepted EmailDelivery plus durable-job service and remains disabled until that interface and every later operational safeguard are available. #48 may expose the capability/service seam and zero-write Relay dry-run behavior without creating a circular dependency on #49.
Ownership and sequencing
Accepted Relay #1 source/OpenAPI contract
+ accepted website #31/#32/#33 service, role, credential, confirmation, and audit foundations
-> website #48 source implementation with deterministic Relay fakes/contract fixtures
-> independent tester + PM + focused commit/merge/push + green website CI
Accepted Relay #2/#3 source contracts
+ accepted #48
-> website #49 ordinary durable-delivery implementation
Accepted Relay #1/#2/#3 deployed at exact sandbox commit/OpenAPI identity
+ accepted #48/#49 and automated/source #50
+ accepted #60 side-effect-disabled rehearsal
+ exact scoped credential/callback/reconciliation/alarm/allowlist safeguards
-> separately authorized one-recipient development `courses` canary
-> #50 HUMAN acceptance
-> #73 aggregate development rehearsal
-> #74 separately authorized production cutover
Dependency meanings:
- Relay #1 is the upstream implementation owner for scoped/expiring credentials, draft revision, immutable published versions, safe typed rendering, zero-write preview/dry-run, and queued snapshot inputs. Its accepted source/OpenAPI contract is required before website #48 engineering.
- A Relay source commit or green Relay CI is not a deployment receipt. Exact sandbox deployment/OpenAPI identity and scoped non-production credential evidence are later integration/canary gates.
- #31 is accepted. #32 and #33 remain required because #48 must consume, rather than invent, Studio/admin identity, capability, high-risk confirmation, credential, and audit contracts.
- #22, #23, and #124 are accepted authority inputs, not open implementation dependencies. Closed-not-planned #106 is historical only and is not a milestone.
- #49 depends on #48's immutable template/version consumer boundary. #48 must not wait for #49 to implement its source-owned management contract; actual email-generating test delivery integrates downstream through #49.
- #50 and #60 do not block deterministic #48 source work. They are later inputs to the protected canary sequence. #73 is downstream of #50 HUMAN acceptance and is never canary authority.
- Production Relay sender/domain activation, production credentials, Datamailer freeze/drain/retirement, and production canary/cutover remain #74/infrastructure/operator work under separate explicit authority.
Website implementation scope after source dependencies pass
- Add shared website application services for Relay template catalog/read, draft create/update, zero-write preview/dry-run, publish, historical republish, and test-send preparation.
- Use the same services from Studio and
/api/v1/admin/; adapters do not contain business rules. - Require Relay's exact
expected_revisionand idempotency contracts. Preserve stale/conflict outcomes without local lost-update recovery or shadow mutation. - Pin and validate the accepted Relay OpenAPI/consumer fixture. Unknown/incompatible contract versions, fields, template keys/versions, contexts, scopes, or response states fail closed.
- Keep Relay runtime and template-management credentials separate, server-side, scoped, expiring, rotatable, and redacted through the accepted #32/#33 boundary.
- Store no mutable template subject/plain/HTML source, example/preview context, rendered body, resolved sender, Relay credential, or raw provider response in website models/files/logs/audit.
- Permit only bounded redacted catalog metadata caching for an unavailable read-only view. Cached data cannot be edited, previewed, published, rendered, test-sent, or treated as current.
- Record actor, capability, template key/version, draft revision, action, outcome, request/correlation/idempotency values, and bounded safe reason. Never audit recipient, raw context, body, credential, or provider payload.
- Mark all Studio/template-management responses private, no-store, noindex, and zero-TTL.
- Provide accessible confirmation, validation, conflict, unavailable, denied, and retry guidance at desktop and mobile sizes.
Acceptance criteria
- Relay is the sole canonical template/version/rendering/sender-policy owner; no website model/file/service becomes a second mutable template-content store or renderer.
- The website pins the accepted Relay #1 source/OpenAPI contract and fails closed on incompatible version/schema drift before mutation.
- Studio and admin API use the same website application services with capability/object scope, expected revision, idempotency, confirmation, audit, error, and response parity.
- Draft updates require the current
expected_revision; stale and concurrent edits return a safe conflict without lost work or a local shadow write. - Publish replay with one idempotency key creates one immutable Relay version; historical republish creates a new version and preserves all prior versions.
- Preview and dry-run use Relay's accepted validator/renderer and create no website or Relay contact/message/event/callback/job/queue/provider side effect.
- Missing, extra, wrong-type, Unicode/length-invalid, malicious HTML/script/URL/header, and unsupported template input return stable actionable errors without unsafe reflection.
- Variables escape by default; authored rich content is sanitized; plain/HTML output has meaningful content/link parity, accessible structure, and no tracking pixel.
- A selected immutable template key/version and sender snapshot cannot change after later draft, publish, or republish operations.
- Wrong-scope, expired, revoked, unscoped, and cross-tenant credentials fail before existence disclosure; raw credentials never enter responses, logs, audit, fixtures, screenshots, or issue evidence.
- Relay timeout/unavailability, stale revision, duplicate publish, unknown key/version, and incompatible response fail safely; a redacted cache is read-only and never a rendering/sending fallback.
- Actual email-generating test-send execution is unavailable until it can create one accepted #49 logical delivery/job; #48 never sends directly, through Datamailer, or through SES.
- No source, test, deployment, credential, recipient, canary, or production evidence is conflated: each later gate records its exact identity and owning authority.
Required verification
- Catalog and draft read; correct/stale concurrent edit; publish replay; changed publish conflict; new publish; historical republish; and immutable version read through both Studio and admin API.
- Preview/dry-run database and outbound spies prove zero contact, delivery, event, callback, job, queue, provider, Datamailer, or SES work.
- Missing/extra/wrong-type context, malicious authored/context input, header injection, unsupported constructs, Unicode, long content, broken links, and safe error focus.
- Positive and negative capabilities, object/tenant separation, expired/revoked/wrong-scope credential, confirmation/replay, redacted audit, private/no-store/noindex, and unavailable/cache behavior.
- Relay OpenAPI/fixture drift, unknown fields/states/version, timeout before/after request, duplicate response, and safe recovery without local canonical mutation.
- Test-send preparation pins an immutable version; any actual send path fails closed until the accepted #49 service is present and never falls back to a direct provider.
Browser and screenshots
The independent tester uses deterministic local Relay fakes only. At desktop and mobile widths, exercise Studio catalog, edit, preview/plain alternative, publish, historical republish, test-send-disabled/preparation, stale conflict, validation/focus, unauthorized, unavailable, and read-only cached states. Inspect every graph-selected screenshot under .tmp/screenshots/ for the intended page, responsive/accessibility behavior, and absence of recipient, raw context, body, secret, credential, provider data, or debug output. Verify equivalent admin API results and negative authorization.
No live Relay call, credential readback, provider request, email, canary, or production access is part of #48 verification.
Lifecycle
- Keep #48 unassigned until Relay #1 and website #32/#33 are accepted at exact source/interface identities.
- PM freezes the Relay OpenAPI/consumer fixture and website dependency SHAs for one isolated current-main candidate.
- The engineer implements and tests without committing or contacting Relay.
- A separate tester recomputes the change-selective plan, runs focused Django plus graph-selected Playwright, validates every criterion, and captures/inspects required desktop/mobile screenshots.
- PM accepts only a complete tester PASS with no pending/required skip.
- The engineer creates a focused
Closes #48commit; the orchestrator locally merges with--no-ff, pushes, and on-call observes terminal green website CI. - Exact Relay sandbox deployment, credentials, and canary remain separately owned downstream gates; closing #48 does not satisfy or authorize them.
Explicit non-goals
- Relay #1/#2/#3 implementation, Relay deployment, credential provisioning/rotation, provider configuration, or infrastructure mutation.
- Website
EmailDelivery, callback/reconciliation, provider-attempt/event storage, domain-purpose wiring, Datamailer migration/retirement, or #50/#60/#73/#74 execution. - A website-owned renderer, mutable body/version table, resolved-sender store, direct SES/Datamailer path, or local render/send fallback.
- Campaign/newsletter authoring, arbitrary template code, tracking pixels, production sender/domain activation, broad-recipient access, real recipient, or controlled canary.
- Any inference of protected/provider/production authority from source acceptance, a deployment receipt, passing tests, or issue prose.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the accepted Relay #1 OpenAPI contract and the cited files in _docs/specs/05-events-registration-email.md, _docs/specs/06-studio-and-admin-api.md, _docs/specs/07-security-privacy-operations.md, and _docs/specs/09-migration-rollout-roadmap.md; implementation is blocked until the stated dependencies pass. Then inspect the shared website services and Studio/admin API adapters, and run focused Django plus graph-selected Playwright verification. Done means both interfaces satisfy the acceptance and zero-side-effect criteria without creating local template storage or a direct send path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, openapi, playwright, python
- Domain
- api, backend, frontend, security, testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100