Needs grooming: Preserve AISL template footer notes through import and rendering
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 25/100
調査の方向性
Read Relay AGENTS, docs/PROCESS, and the existing template model and service code, including mailing.models.py, mailing/services/api.py, transactional_versions, and transactional_markdown. Run the relevant baseline tests plus make test and make lint before any extraction. Done means the approved template ownership preserves schema, API, immutable versions, selected rendering, and no-UI behavior with the specified footer tests passing.
索引モデルが issue の本文から書いたものです。
説明
Preserve authored template footer notes in the Relay backend
Stage and dependencies
Proposed PM grooming for existing #29, under preservation parent #30 P01/P02. Implementation is blocked pending the Relay model/template API/render owners' exact scope/path acknowledgements, including the current ui/aisl work and reserved migration0030. Do not open a duplicate issue or assign that migration number from the reviewed source alone.
Read Relay AGENTS, docs/PROCESS, PM role, architecture/data-model/API/operations and #30. Reviewed source is cdf3a9a25de8bd63af8ee45285983d28a3aa13a0; donor semantics are bound to AISL f9a3b0432864d40f6f12a85382df4a25c4e3f98f. Current source references are static findings, not test proof.
The user requires existing authored footer content and recipient/operator experience to survive. Existing AISL screens/routes/tasks remain through thin adapters until preservation is accepted. This issue adds a backend metadata/render contract; it authorizes no UI controls, navigation, layout, copy, route removal or redesign. Agents do not access production databases/credentials. Actual export/import, publish, sends, deployment and adoption are later authorized owner work.
Problem and goal
AISL EmailTemplateOverride replaces subject/body/footer as one record. footer_note is literal authored text, up to500 characters in the donor field, with empty default. Its HTML chrome escapes the note; the plain-text renderer appends it with presentation-only outer whitespace trimming, before verification and unsubscribe actions. Footer text is not a second Django-template program or trusted HTML.
Relay drafts, immutable versions, API payloads, import/transfer projections and render sources currently omit footer_note. wrap_email_html already accepts it but the version/send path does not pass it; plain text currently carries substituted Markdown without footer. Preserve the field through one template-domain owner and a canonical snapshot/render source. Never strip or truncate stored footer content or reconstruct it from body/subject.
Bounded scope and child boundaries
- This issue owns footer field storage and validation, canonical draft/version serialization, immutable publication copy, selected render-source propagation, and native footer composition/render contract. Existing endpoints, model identities, table names and import paths stay stable.
- The P01 normalized-bundle consumer child owns whole-bundle preflight/atomic apply, dynamic override-only catalog/context metadata and file/override reconciliation. It calls this issue's footer validator/serializer; no AISL Python import, second exporter or per-file partial importer is added here. Do not fix unrelated subject stripping/classification/context rules inside #29.
- P02 owns the generic first-class rendering profile and complete subject/body/plain-text/HTML/chrome/footer/action parity. #29 carries literal footer data and supports escaped HTML/plain-text composition through that native contract, without a site import or copied AISL renderer. The native footer contract must preserve full content and placement; native Relay default chrome is not proof of donor equivalence. Adoption remains blocked until P02 synthetic recipient comparison passes.
- Dynamic verify/unsubscribe decisions, greeting/timezone and delivery-time links remain minimal AISL adapter P07 inputs. Footer author text is distinct from those policies and must not mint tokens, change classification or create a team sender kind.
- Existing old-instance transfer and #26 history work remain owned separately. Generic template transfer field projection may need a coordinated metadata seam to prevent future field loss, but no production rerun or history import belongs here. Exact projection changes need the transfer owner's ACK.
Contract
- Store footer_note on draft and immutable published version with empty-string default for legacy rows. A string, including empty/whitespace-only and Unicode/multiline content, is retained exactly in storage and API/snapshot output. Proposed capacity matches donor's supported500 characters; accept exact500 and reject501 rather than truncate. Reject explicit null, booleans, numbers, lists and objects with field-scoped validation before persistence. If owner/schema review selects a wider generic capacity, record it and its boundary tests; never choose a narrower capacity or silently coerce values.
- Existing full-replacement template PUT retains documented behavior: omitted footer means empty, explicit empty clears the draft, invalid footer leaves the entire draft unchanged. GET/upsert/version/publish output exposes one footer key consistently. Unknown/foreign template/version/client isolation and existing error/status shapes remain. Field omission semantics of separate generic transfer/bundle protocols are versioned by their owners; absent legacy footer maps to empty, not a destructive change to immutable snapshots.
- Publishing snapshots footer together with the same draft subject/body/context/category at that state transition. Later draft edits/clearing affect only a newly published version. Existing published versions remain immutable; old rows gain default empty rather than receiving a later draft footer. Resolve explicit version, latest published version, or never-published draft with existing precedence. No fallback that takes a published body and current draft footer.
- One canonical selected render source feeds preview, dry run and durable send. The selected footer is composed exactly once into escaped HTML and a plain-text counterpart. Do not template-evaluate its {{variables}} or {%blocks%}, mark it safe, Markdown-render it, duplicate it, or persist trimmed text. Plain-text presentation may follow donor outer trimming; comparison records this explicit behavior. Verification/unsubscribe action placement follows P02/P07 contract, with authored footer before those actions. Full pre-rendered HTML/text sources need an explicit supported composition/profile contract; reject unsupported nonempty-footer/source combinations before message/queue work rather than silently omit or double-wrap existing content.
- Preview and dry-run remain no-write/no-queue/no-network operations. Real/test-send allowlist, idempotency, suppression, render-source precedence and audit semantics remain existing Relay contracts; #29 does not change transport retry or live-history behavior. Parent donor test-send equivalence remains its separate preservation gate.
- Existing admin/other forms must not inadvertently acquire a new footer control through model auto-discovery or clear a backend footer on an unrelated edit. Preserve current fieldsets/rendered workflow and bind future editing UI to its own owner/card. No visible feature disappears.
Cohesive ownership and size strategy
User-required portable coding standard applies: one business owner, DRY, thin APIs, explicit transactions, no ternaries, simple loops, new functions at most30 lines/new handwritten files at most300. Do not grow already oversized files/functions without a genuine documented tool/framework/cohesion constraint. A two-field addition or absent mechanical size gate is not an exception. Committed Relay has no coding-standard file; repository-specific configuration/commands follow Relay, and a guidance port is separate.
Proposed extraction for owner review, not arbitrary fragments:
- Extract the complete coupled EmailTemplate and EmailTemplateVersion declarations, including Meta/constraints/indexes/managers/immutability, into one cohesive template-domain model module (proposed mailing/template_models.py). Keep mailing.models.EmailTemplate/EmailTemplateVersion explicit re-exports so existing callers/admin/tests remain stable. Preserve Django app/model labels, db_table, relationships, related names, discovery and migration deconstruction.
- Resolve their existing shared TimeStampedModel dependency without a circular import: a cohesive shared abstract model-base owner (proposed mailing/model_base.py), explicitly re-exported through mailing.models. Template-to-client references use equivalent lazy relationships if needed. Move the whole existing base once; do not clone fields or invent an inheritance/mixin hierarchy merely to hide line counts. Verify identical schema state before the intentional footer migration. If this extraction conflicts with current owner work, stop/re-groom rather than append fields under an automatic waiver.
- Extract the complete template payload/validation/upsert concern from oversized mailing/services/api.py into a cohesive template service (proposed mailing/services/template_contracts.py), retaining public API imports/error type/transaction boundaries through thin forwarding or re-exports. Generic validation/error helpers keep one owner; avoid circular dependencies. This moves a business concern, not one-field helpers dispersed across files. Preserve existing subject/body behavior while adding footer validation.
- Reuse the existing transactional_versions render-source/publication owner and transactional_markdown composition owner. Use a shared renderer seam for footer, not competing preview/send implementations. Any oversized transactional/transfer/API-doc module only calls the extracted owner or coordinated canonical metadata projection; actual unavoidable framework/cohesion exceptions require written review, not a preset line budget.
Verification and acceptance
- Baseline behavior characterization before extraction, then same tests after extraction: Django apps.get_model and stable mailing.models imports, admin registration, model labels/tables/constraints/foreign keys; migration autodetection sees no remove/recreate/rename solely from extraction. Fresh and pre-existing database migrate/reverse/reapply retain draft/version counts, IDs, relations and published text. New footer field is the sole intentional schema delta; allocate next migration after current-owner ACK.
- API tests: empty/missing/explicit clear, Unicode/multiline/whitespace, exact500/501, wrong types, foreign client and invalid footer atomic rollback. Assert byte-identical stored/returned/snapshot values and unchanged subject/body. Generic bundle/transfer metadata contract fixtures consume the same validator/serializer without running a donor importer or network.
- Version tests: draft footerA→publishv1→edit/clear→publishv2; explicitv1/latest/draft preview and send select the correct footer, never hybrid snapshots. Existing immutability/update/delete/version precedence tests pass. Existing queued/rendered messages are not rewritten by migration.
- Render tests: literal tags/HTML characters escaped and not evaluated, nonempty and empty footer, no double composition; HTML/plain-text selected-version preview/dry-run/send equality and safe unsupported-source rejection before any durable work. Synthetic donor-bound footer fixtures compare HTML escaping/placement and plain-text content/order with named/nameless/context variants. P02 retains complete donor chrome/format/action parity across dynamic inventory; #29 capability acceptance alone never establishes it.
- No-UI tests: current admin form fields/fieldsets and unrelated edit preserve backend footer; existing catalog/routes/operator view/template tests remain. Independently rendered recipient evidence is required where output changes; no screenshot exemption based on backend-file names alone.
- Independent Tester runs fresh relevant Relay unit/service/view tests and current make test/make lint gates, with SES/SQS stubs and assigned environment ownership; records actual commands/exits/frozen hashes. PM reviews actual terminal evidence after role gates. No production sends or borrowed source/CI evidence.
Done when this bounded footer contract and its cohesive ownership/extraction are independently tested/accepted, exact write overlaps have ACKs, docs/API schema state truthfully report support, and existing APIs/UI/model identities/published versions are preserved. Parent #30 remains open; normalized whole-bundle import, complete rendering-profile parity, real overrides, D13/R6.1 and A6.1/adoption/cutover receipts remain separate pending gates.
- 主要言語
- Python
- スター
- 0
- フォーク
- 0
- 平均マージ
- 11分
- マージ済み PR(30日)
- 4
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートなし
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
DataTalksClub/relay のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
DataTalksClub/relay#48 ·
-
enhancement
難易度 5/5 1週間以上 初心者へのやさしさ 20/100
DataTalksClub/relay#49 · コメント 3 件 ·
-
bug
難易度 5/5 1週間以上 初心者へのやさしさ 20/100
DataTalksClub/relay#42 · コメント 7 件 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 15/100
DataTalksClub/relay#41 · コメント 9 件 ·
-
community-base enhancement
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
DataTalksClub/relay#39 · コメント 6 件 ·
DataTalksClub/relay の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
pylint-dev/pylint#11791 ·
メンテナーはふだん 1 日以内に返信
-
Rasterio granule reads never retry, so one 503 (Service Unavailable) fails the whole request対応中かも @chuckwondo が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
developmentseed/titiler-cmr#305 ·
メンテナーはふだん 1 日以内に返信
-
community enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
メンテナーはふだん 1 日以内に返信