Needs grooming: Preserve AISL template footer notes through import and rendering
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 25/100
Direzione di ricerca
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.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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.
- Lingua principale
- Python
- Stelle
- 0
- Fork
- 0
- Merge medio
- 11m
- PR unite (30g)
- 4
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Nessun modello di pull request
- Nessuna guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di DataTalksClub/relay
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
DataTalksClub/relay#48 ·
-
enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 20/100
DataTalksClub/relay#49 · 3 commenti ·
-
bug
Difficoltà 5/5 Più di una settimana Idoneità per principianti 20/100
DataTalksClub/relay#42 · 7 commenti ·
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
DataTalksClub/relay#41 · 9 commenti ·
-
community-base enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
DataTalksClub/relay#39 · 6 commenti ·
Tutte le issue di DataTalksClub/relay
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
earthtojake/text-to-cad#758 ·
I maintainer di solito rispondono entro 1 giorno
-
domain:upgrades enhancement needs-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
gke-labs/kube-agents#4634 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
agardnerIT/opamp-server-py#116 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
enhancement good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
elviskahoro/sdk-python-attio#144 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno