Scope and status
Draft design for a center’s daily and periodic reports and staff replies. All examples are synthetic. This page proposes behavior; it does not enable receiving, change senders, provision infrastructure, or apply a schema migration. Invitations and paid custom-domain entitlements are separate designs. Parents should reply to a report and reach authorized center staff, who can read, assign, answer and resolve the conversation beside its student and parent records. Undeliverable addresses must stop consuming sends. Defaults below require product, security and privacy acceptance before activation. Preserve report approval, unsubscribe, workspace permissions and unknown-send-outcome fences.Verified source baseline
Paths and lines below refer to commit691e9f70ad7a8c071c57b85752a4b8b56b8e4bc6, inspected without customer data.
The supplied brief identifies notifications@tuturuuu.com and SES
ap-southeast-1 as the operational sender/region. Code supports configurable
workspace credentials; this inspection does not establish live configuration.
See the report reply foundation and
report behavior. This proposal extends their
contracts; it must not be interpreted as changing the disabled foundation today.
Reply address and delivery flow
Keep the currently approved From identity until the project owner approves a change. Configure one verified inbound subdomain, illustrated only asreplies.example.test, with a workspace routing policy. Verify DNS ownership, MX
routing and a synthetic ingress canary before readiness can become true. Sending
identities require SES verification and SPF/DKIM/DMARC alignment independently
of inbound MX verification. No DNS or sender change is authorized by this draft.
Proposed address: r2.<opaque-id>.<mac>@replies.example.test. Use a 128-bit random
identifier and a truncated 128-bit HMAC-SHA256, base64url encoded; the resulting
local part fits 64 bytes. MAC input is a canonical versioned tuple containing the
opaque ID, workspace, report/post generation, recipient binding, expiry and key
version, resolved from private storage. No student name, address or record ID
appears in the address. Constant-time verification, a versioned keyring, expiry
and revocation prevent tampering and support rotation. Store a lookup digest and
encrypted reconstruction material; never expose token values in logs or UI.
Extend the existing identity API with a versioned codec; do not silently change
its 48-hex parser. Retain legacy decoding only for legitimately issued identities
with their original scope and validity. Preserve immutable accepted/unknown send
history. Proposed token validity is 180 days; expired replies enter a bounded
staff-only exception queue without disclosing report contents or sending a bounce
loop. Validate this lifecycle against the eventual retention decision.
Cloudflare Email Routing hands raw mail to a Worker. The Worker verifies the exact
envelope domain and token, authenticates transport provenance, validates the
current workspace/record relationship, and admits durable work. Token possession
allows routing only: it does not authenticate a parent or authorize disclosure.
Require the bound parent address and verified sender-authentication evidence;
forwarded mail, changed guardians, ambiguous identity or failed authentication go
to restricted review. Never trust caller-supplied Authentication-Results headers.
A staff member must verify a changed contact through the existing contact process.
Use the token binding to select the workspace before matching In-Reply-To or
References against stored outbound/inbound Internet Message-IDs in that same
workspace and conversation. Store SES provider IDs separately from RFC IDs.
Conflicting token/header targets go to review; missing headers may start a thread
under the valid bound report. Subject matching alone must never join students or
workspaces. Deduplicate by transport event and raw digest, with collision review
for reused Message-IDs. Persist before acknowledging; failed persistence retries
within the configured budget. An acceptance timeout is reconciled, not resent.
Staff inbox and safe replies
Provide a workspace inbox within the report and contact experience, linked to the student, verified parent relationship, original report/post and read-only report snapshot. Reuse mail storage but grant no access to the shared notifications mailbox. Staff roles are viewer, responder, manager and suppression administrator; membership alone is insufficient. Enforce workspace and record permissions on reads, writes, search, attachment downloads and realtime events. Support unassigned/mine/team queues, assign/reassign with optimistic concurrency, reply drafts with approved templates and report context, and open/pending/resolved states. Replies use the center’s approved sender and the same protected send path; never allow arbitrary From, recipient, CC or BCC fields to create an open relay. Show send failures and suppression reasons, and preserve drafts. Accepted by SES is distinct from delivered. New eligible parent replies reopen resolved threads. Proposed SLA: first human response within one business day, using the workspace timezone and staff calendar. Measure from the oldest unanswered eligible inbound message, pause only for explicit waiting-on-parent state, and alert assigned staff and then the manager once per escalation level. Auto-replies never satisfy SLA. Provide unread, status, assignment, report period, student, overdue and delivery filters; keep global suppression details hidden from ordinary workspace staff. DetectAuto-Submitted, mailing-list/precedence signals, vacation headers, DSN MIME
and empty-envelope bounces. Classify OOO/auto-replies separately, avoid reopening
or generating automatic acknowledgements, and allow manual reclassification.
Only authenticated SES events may create infrastructure suppression; a forged
bounce-shaped email cannot blacklist an address. Human reports of abuse enter
staff review. Add bilingual reply instructions only after qualified routing:
“Reply to this email to reach the center” and
“Trả lời email này để liên hệ trung tâm”.
Quarantine attachments before display or forwarding. Check MIME signatures,
allowlisted types, decompressed size, archive depth and malware verdict; reject
executables and password-protected archives unless a separate safe review process
exists. Default to 10 MB per message, 5 attachments, 20 MB expanded total and one
archive layer. A timeout or unavailable scanner stays quarantined. Use a private
object store, short-lived authorized downloads, sanitized HTML and blocked remote
images. No public scanner uploads of parent/student data. A compatible scanning
service and its processor agreement are rollout prerequisites.
SES events and suppression
Configure a dedicated SES configuration set inap-southeast-1, publishing send,
delivery, bounce, complaint and delivery-delay events to a Standard SNS topic.
Attach the set and opaque correlation tags on every relevant send, including raw
MIME staff replies. Limit SNS publish permission to the SES source account and
configuration set. AWS documents this configuration-set destination.
SNS delivers to a Cloudflare HTTPS webhook. Verify the signature over AWS’s
canonical envelope, require the expected topic/account/region, and validate the
certificate chain and exact HTTPS SNS certificate host/path with redirects
disabled. Verify subscription confirmations before confirming through a pinned
AWS endpoint; never fetch arbitrary SubscribeURL or certificate URLs. Prefer
signature version 2 and reject unconfigured versions. Follow AWS’s
SNS signature verification.
Bound payloads, reject malformed events, deduplicate topic + SNS message ID, and
also deduplicate semantic delivery events by provider send/recipient/type.
Timestamp policy must accommodate documented retries; old unrecognized events
require reconciliation rather than silently restoring sending.
Resolve the trusted send ledger to workspace and recipient; event tags alone are
not authority. Atomically persist the event and hard-bounce/complaint suppression
before acknowledging success. Materialize suppression synchronously on this path;
queue expensive analysis afterwards. If persistence is unavailable, return a
retryable failure and halt affected outbound admission until event health recovers.
Unknown send IDs enter a restricted reconciliation queue and raise an alert.
Apply conservative address normalization consistently (trim, domain normalization,
existing case policy); do not collapse plus tags or provider-specific dots.
Role-based and disposable addresses are WATCHED/review signals rather than blanket
rejections of legitimate guardian contacts. Aggregate domain failure signals with
minimum volume and a bounded hold; security operators may impose a global domain
block with evidence. One center’s soft failures must not block unrelated centers.
Use a single authoritative pre-send decision at enqueue for feedback and again
immediately before provider invocation for races. Return
skipped with reason
codes such as workspace_blacklist, global_hard_bounce, complaint,
watch_cooldown, unsubscribed or suppression_unavailable; distinguish retryable
holds from terminal skips. Suppression committed before admission wins; mail
already accepted by SES cannot be recalled. Serialize per-recipient admission
with suppression updates and minimize the remaining provider handoff window.
Never let a generic retry, test-send or manual reply bypass protection.
Import the existing manual email_blacklist idempotently using a private export
or server-side read, checkpoint and dry-run counts. Preserve email/domain/pattern
scope, provenance, reason and original block semantics; ambiguous patterns require
review and remain enforced by the legacy checker. Keep existing global blocks
global. Reconcile counts/checksums and concurrent writes before switching readers;
dual-read the union during transition, never use last-write-wins to clear blocks.
No customer export, address list or raw SNS payload belongs in a PR or log.
Dashboard and alerts
Workspace staff see sent, accepted, delivered, skipped with reason, WATCHED, blocked, unanswered and overdue counts. Operators see configuration-set/account health, webhook lag, last verified event, queue age, DLQ, scanner failures and remaining work budgets. Display time window and denominator with bounce/complaint rates; use provider-send/recipient counts and exclude duplicates. Keep SES account reputation metrics distinct from workspace application rates. Proposed early warnings are 2% hard-bounce and 0.05% complaint rates (minimum 100 sends for rate warnings; any complaint still suppresses immediately), or 80% of current SES quota. These are internal proposals, not claims about AWS limits. Infrastructure and security on-call own alerts near account limits. Add a five-minute stale-event warning while traffic exists, and deduplicate/escalate alerts through existing operational channels. Audited restore shows actor, scope, reason, evidence, previous state and result; ordinary staff see only actionable workspace information, never another workspace’s history.Cloudflare ownership and cost stop fences
Follow Cloudflare backend ownership: Workers handle ingress and send admission; Queues isolate parsing/scanning and outbound jobs; existing Cron Control handles bounded SLA, retention and recheck batches. Supabase remains the system of record. Next routes provide authenticated UI/API adapters only. Do not add Vercel background work, pg_cron, Edge Functions or Trigger.dev processors, or run duplicate legacy and new queue owners. Before pilot, approve workspace and global daily/monthly limits for sends, accepted bytes, object storage, scan bytes, queue operations, database calls and alerts. An unconfigured budget means disabled. Reserve worst-case units atomically before work, including retry amplification; reconcile actual use without refunding unknown outcomes. Initial qualification bounds: batches of 50, three attempts per job within 24 hours, one scan per content hash/version, one SLA alert per escalation level, finite DLQ retention, and operator-approved replay with its own budget. Maintain a durable global/workspace stop state and monotonic epoch checked before every paid operation, provider submission, retry, alarm and queue re-enqueue. Recheck after leases or waits; restarting must not reset counters or stop state. Completed, suppressed, expired, exhausted and cancelled jobs schedule no further work. Stop outbound sends first; reserve a separate bounded budget for receiving suppression events. If that budget is exhausted, keep sends stopped and persist an explicit reconciliation gap. Automatic SNS/queue retries must have finite policies; total shutdown disables upstream subscriptions/routing after durable capture or explicitly recorded loss, not endless failure responses. An application fence cannot eliminate unavoidable ingress invocations or bytes already accepted by providers. Include an operator upstream-disable runbook and measure those residual costs. Billing alerts, ingress rate limits and CPU caps alone do not prove a spending cap. Before activation record service-specific operation counts, failure/restart tests and stop evidence in the adoption guidance.Privacy and retention
Treat parent and minor correspondence, student links and suppression fingerprints as personal data. Vietnam’s PDPL, Law 91/2025/QH15 is effective from 1 January 2026. Privacy counsel must confirm applicable rules, controller/processor roles, lawful basis, child/guardian requirements, notices, rights handling and cross-border processing before pilot; this is a design gate, not a legal determination. Permission to receive reports does not automatically authorize marketing, AI training or unrelated reuse of replies. Proposed configurable retention: raw MIME/quarantine 7 days, attachments 30 days, conversation content 180 days after resolution, and minimized operational audit 365 days. These are product defaults for review, not statutory periods. Minimize report snapshots; keep content out of telemetry and alert payloads. Encrypt content and contact addresses; use keyed address digests for matching, with key rotation and restricted access. Pseudonymized data remains protected. Delete expired objects, derived text, search indexes and attachments with bounded Cloudflare jobs; propagate deletion tombstones through retries and backups under a documented backup-expiry policy. Existing immutable reply identities need a reviewed retention-specific purge mechanism; never weaken send-outcome fences by ordinary deletion/requeue. Retain only justified minimal suppression fingerprints and reasons while necessary to prevent unwanted contact, review necessity annually, and have counsel decide erasure exceptions and legal holds. Staff-only RLS and record authorization apply to service RPCs too; test tenant isolation, removed staff, changed guardians, signed-download expiry and access audits.Schema sketch only
Conceptual extensions, not executable SQL or a migration. Final names, constraints, RLS and retention must be reviewed alongside the existing private mail schema.
All workspace relationships require matching tenant keys and checked current
permissions. Only infrastructure operators manage global state. Scoped staff APIs
return block decisions without leaking other tenants’ events. Keep existing
blacklist/bounce functions as adapters during rollout; one policy evaluator owns
all sends, so old and new schemas cannot disagree permissively.
Effort ranges and phased rollout
Ranges are incremental engineering dev-days for one experienced engineer per slice, including implementation, focused tests and review fixes. They assume reuse of the foundations above; DNS/provider approvals, legal review and calendar waiting are excluded. Scanner integration and schema reconciliation drive the upper bounds. Total sequential effort is 33–54 dev-days, not elapsed time.- Foundation/shadow: A then B, with policy simulation on synthetic events; preserve existing suppressions and reconcile the manual import. Production shadowing requires separate authorization and private telemetry.
- Suppression canary: enforce B for one admitted workspace, initially behind explicit enablement. Land E’s stop/budget controls before any billable pilot. Verify that queued sends skip immediately after accepted adverse events.
- Reply canary: C and D on synthetic recipients; qualify both daily and periodic reports, token rotation/expiry, retries, scans and staff permissions. Only then enable Reply-To and instructional copy together.
- Controlled rollout: F with user approval before real-parent mail. Expand workspace cohorts based on observed delivery and inbox handling, retaining per-workspace stop switches and an accountable staff owner.