logicspike/docs

Communication

Readiness checklist: all ten gates green before submitting

Gates are named R1 to R10 so they cannot be confused with the gap-log IDs (G1 to G70, in gap-log.md).

Fill in Done on / by / evidence as each gate is met. Evidence is a file under evidence/ (see evidence-checklist.md) or a link.

Check the AWS account first. The aws commands below must run against the SES account: the one signed in as founder@vlozi.app, where vlozi.app is a verified identity in Mumbai. On 2026-10-07 the CLI on the development machine was signed into a different account (829547187034) that has no SES identities, configuration sets or SNS topics, so its output says nothing about Vlozi (gap-log G77). Run aws sts get-caller-identity --query Account --output text before any command here, or use the console equivalents (the identity's Authentication tab, the SES account dashboard, and Suppression list → account-level settings).

Commands are PowerShell. DNS checks are read-only and safe to run any time. Run wrangler commands from the app's folder with $env:CLOUDFLARE_ACCOUNT_ID = "72fe41e9f39ad60cfb6937bb26ab50c3" set, or wrangler may use a cached wrong account.


R1 — Operator identity published

The case, the policies and the website must all name the same operator and the same address. The site reads them from apps/website/lib/legal.ts.

  • Operator decided (2026-10-07): Dipanshu Vishwakarma, trading as Vlozi. An individual; the business is not registered, so nothing may imply a company
  • Address decided and spelling confirmed (2026-10-07, public): Devgaon, Azamgarh, Uttar Pradesh 276201, India. Spelled "Deogaon" until 2026-10-26, when it changed to the Aadhaar spelling so the site, the AWS account and AWS's identity verification agree (website redeployed the same day, Pages 904557f5, commit 42c92e40 on main)
  • Both appear in Terms, Privacy, Acceptable Use, Anti-Spam, Abuse and the site footer. Deployed 2026-10-07 and checked on the live pages the same day
  • The Vlozi workspace's own organisation address (Newsletter settings, Footer) is set to the same address. It needs the owner's OK before it is written through the comms sender-settings tool (gap-log G63)

Done on / by / evidence: ______

R2 — AWS account in good standing

  • Valid payment method on file: UPI AutoPay, set as default, AutoPay on (checked 2026-10-26, Billing → Payment preferences)
  • Account contact details match the operator (Account → Contact information, 2026-10-26: the operator's name and the full address as the Aadhaar prints it; the website shows the short form, Devgaon, Azamgarh, Uttar Pradesh 276201). The billing address under Payment preferences still showed an older, misspelt form of the same area on 2026-10-26 and could not be edited there; re-check it in a day
  • Root user MFA enabled (already on, checked 2026-10-26)
  • Support plan confirmed in the console (Support → Your plan): Basic Support (2026-10-26). Enough to submit; Developer is only needed to open a technical case after a denial
  • Alternate contacts (billing, operations, security) set to your existing private inbox, which does not depend on vlozi.app being up (set 2026-10-26; decided 2026-10-07, gap-log G56, G63)
  • AWS confirms the account is fully verified (gap-log G79). On 2026-10-26 CloudShell would not start ("Your account verification is in progress"), and an AWS Health event "AWS ACCOUNT CUSTOMER VERIFICATION REQUIRED" (India customer verification) had opened that day. Billing → Account → Customer verification showed the name verified but the address unverified since 2026-07-04: the address typed in July did not match the Aadhaar. Fixed 2026-10-26: the account contact address was set to the Aadhaar wording and Aadhaar was verified through DigiLocker; name and address both Verified (20:42 IST). The address itself is deliberately not written here
  • The AWS root address founder@vlozi.app receives a test mail from an outside account. A Cloudflare rule delivers it to a personal inbox, and AWS replies to the case arrive there

Done on / by / evidence: ______

R3 — Domain authentication

DKIM

aws sesv2 get-email-identity --region ap-south-1 --email-identity vlozi.app --query "DkimAttributes.[Status,CurrentSigningKeyLength,SigningAttributesOrigin]"
  • Status is SUCCESS; note the key length and origin (the case text says nothing about key length unless this shows 2048). 2026-10-26, SES console: DKIM configuration Successful, signatures enabled, Easy DKIM, current and next signing length RSA_2048_BIT. So "2048-bit DKIM" is true

Custom MAIL FROM (SPF alignment)

aws sesv2 get-email-identity --region ap-south-1 --email-identity vlozi.app --query "MailFromAttributes"
Resolve-DnsName bounce.vlozi.app -Type MX
Resolve-DnsName bounce.vlozi.app -Type TXT
  • MailFromDomain is bounce.vlozi.app and MailFromDomainStatus is SUCCESS (set 2026-10-26 with "Use default MAIL FROM domain" on MX failure; Successful in the SES console about 30 minutes after the records went live, 2026-10-26)
  • MX is 10 feedback-smtp.ap-south-1.amazonses.com (live on 1.1.1.1 and 8.8.8.8, 2026-10-26)
  • TXT is v=spf1 include:amazonses.com ~all (live on 1.1.1.1 and 8.8.8.8, 2026-10-26)

DMARC

Resolve-DnsName _dmarc.vlozi.app -Type TXT
  • A record exists with reports (today: p=none with Cloudflare's report address) and a week of the digest has been read: SES and Resend both pass. 2026-10-26, Cloudflare DMARC Management, last 30 days: 7 emails reported, 7 DMARC pass, 0 fail; "Amazon.com, Inc." 6 (100% DMARC, SPF aligned and DKIM aligned; Resend sends through Amazon, so its mail is in this row) and "Cloudflare, Inc." 1 (100%). Low volume, so p=none stays for now
  • Optional: p=quarantine; pct=25 for a few clean days, then pct=100, with adkim=r; aspf=r and the Cloudflare rua kept. The case text names whatever DNS shows that day, so this is not required
  • A received message's headers (Gmail "Show original") show SPF pass, DKIM pass, DMARC pass, and the SPF line names bounce.vlozi.app. Use a message SES sent (the comms log shows provider: ses); a message that failed over to Resend proves nothing here

Done on / by / evidence: ______

R4 — Abuse and postmaster mailboxes work

Which addresses, and why, is decided in contact-addresses.md. As of 2026-10-06 they are mailboxes on vlozi.app in Vlozi's own workspace (the workspace that holds the verified vlozi.app domain). The comms worker receives <name>@vlozi.app and delivers it into the account on that address; replies leave from the same address through Resend. They are not Cloudflare rules. Mail to an address nobody claimed bounces (since 2026-10-21, gap-log G11), but a failed lookup still loses mail silently, so each address needs a real test, not an assumption.

  • abuse@vlozi.app: test mail from an outside address appeared in the mailbox on 2026-10-26 (owner's personal Gmail; filed under the abuse mailbox)
  • postmaster@vlozi.app: appeared on 2026-10-26 (same Gmail; filed under the postmaster mailbox)
  • security@vlozi.app: appeared on ______
  • hello@vlozi.app: appeared on ______. Decided 2026-10-07 (gap-log G55): the Cloudflare rule stays, so this address is received in the operator's personal inbox, not the Mailbox. Tick this when the outside test mail arrives there, and write that here
  • privacy@vlozi.app: appeared on ______
  • legal@vlozi.app: appeared on ______
  • ops@vlozi.app (private; vendor contact): appeared on ______
  • A reply sent from the dashboard from one of them reached the outside account, From <name>@vlozi.app (2026-10-26: reply from abuse@vlozi.app, shown Delivered in the dashboard)

Evidence so far (2026-10-06; platform-sent tests, not an outside account): ten mailboxes exist. A test to each of abuse, postmaster, privacy, security, ops, legal, support, billing and info was seen arriving at the comms worker and filed by the Mailbox (worker logs). hello@ did not reach the worker (G55). A reply from a Vlozi mailbox to an outside Gmail address arrived with From and Reply-To set to that mailbox, signed by vlozi.app. Also on 2026-10-07 at 07:44 UTC the comms log records a reply sent from a Vlozi mailbox to the owner's Gmail (source mailbox, provider resend, delivery status delivered), which means a mail from that Gmail reached a role mailbox and a reply came back; which address it was has not been written down. The boxes above stay unticked until the outside-account test has been run for each address.

Done on / by / evidence: ______

R5 — Bounce and complaint pipeline proven

Use the platform's own mail. A direct aws sesv2 send-email call writes no log row, so no suppression row can appear, and tenant mail never reaches SES (R6). In the Vlozi workspace, open Team → Invite, invite each address below, then revoke the invitations. Each invitation counts toward the 5-per-recipient-per-day limit and holds a seat while it is pending.

Invite Expected
success@simulator.amazonses.com Delivery event reaches comms
bounce@simulator.amazonses.com Bounce event, suppression row written, a second invitation to it is blocked
complaint@simulator.amazonses.com Complaint event, suppression row written
suppressionlist@simulator.amazonses.com account-level suppression bounce handled
  • The comms log shows provider: ses for each send, and each result is visible in the logs or the ops "Email suppression" page (screenshots). 2026-10-26, invitations from the Vlozi workspace, watched with wrangler tail on comms: every simulator send went through SES ((ses) message ids); success@ recorded sent then delivered, bounce@ bounced, complaint@ complained, suppressionlist@ bounced, and a second invitation to bounce@ was refused before sending ("AUTH MAIL SUPPRESSED … (hard_bounce)"). For contrast, the same invitation to the owner's unverified Gmail was refused by the SES sandbox ("Email address is not verified") and delivered by the Resend fallback, as designed
  • The SNS subscription shows a real ARN (confirmed): the delivery, bounce and complaint events above arrived from AWS and were accepted (2026-10-26)
  • The webhook rejects an unsigned POST: curl.exe -i -X POST https://api.vlozi.app/comms/v1/webhooks/ses -H "Content-Type: application/json" -d "{}" returns a 4xx (401, 2026-10-26)
  • aws sesv2 get-account --region ap-south-1 --query "SuppressionAttributes" recorded; note whether both BOUNCE and COMPLAINT are listed (the case text only says the account list is enabled if they are). 2026-10-26, SES console (Suppression list → Account-level settings): Enabled, reasons "Bounce and complaints", list empty. Our code never sets a configuration set's own suppression options, and the hand-made vlozi-platform set (all platform mail) shows "Use account level settings" (checked 2026-10-26). Its reputation metrics were "Not tracking" that day; the account-level metrics the alarms use are published regardless

Done on / by / evidence: ______

R6 — Declared-use guard shipped

SES carries platform mail only until the tenant-mail request is approved. Deployed 2026-10-06 (comms, newsletter-service, mailbox, forms-service). Deployed is not verified: the boxes below are the proof.

  • comms, newsletter-service, mailbox and forms-service deployed together (2026-10-06)
  • SES_TENANT_SENDING is not set on the comms worker: npx wrangler secret list from apps\communication (names only), checked 2026-10-07
  • A tenant send from a mail.vlozi.app mailbox (a form notification, or a reply from a role mailbox on that domain) is refused 503 TENANT_SENDING_NOT_ENABLED; the comms log shows it
  • A platform send to a verified recipient shows provider: ses in the comms log. An unverified recipient fails over to Resend while SES is in the sandbox; that is expected
  • You accept the customer impact: while the guard is on, workspaces on mail.vlozi.app cannot send campaigns, mailbox replies or form notifications (gap-log G22, G23). Mail from vlozi.app goes through Resend and still works

Done on / by / evidence: ______

R7 — Platform-mail abuse bounds shipped

Manager deployed 2026-10-06 (8284200f). Deployed is not verified: the 429 checks below have not been run. The two limits interfere, so use the methods given.

  • manager deployed (2026-10-06)
  • Sign-up: the 6th request from one IP address within 15 minutes returns 429 (use made-up addresses; each attempt counts)
  • Code resend: the 11th verify-email/resend from one IP address within 15 minutes returns 429. Use a different made-up address each time: a repeat for one address hits the 60 s cooldown first, and an unknown address answers 200 but still counts toward the IP limit
  • Invitations: the 6th invitation to one address in a day returns 429, and a 4th resend of one invitation within an hour returns 429. Use your own address and revoke the invitations afterwards, because each takes a seat while pending. A workspace is also limited to 30 invitations an hour
  • Email verification is required before a workspace can be created (already true: onboarding.ts)

Done on / by / evidence: ______

R8 — Public site accurate, policies published

Every URL must return 200 and say what the case says. Policy text lives in apps/website/app/*/page.tsx; the long-form drafts are in ../../legal/.

Deployed 2026-10-07, by the owner. The live text was read the same day and matches the repository: operator and address, venue, refund and agency wording, the suppression and credit wording, and no old phrases. The sitemap lists the four new pages. The pre-flight below was meant to come first; two items were not done and are now overdue, because the live Abuse and Anti-spam pages promise them:

  • LEGAL_EFFECTIVE in apps/website/lib/legal.ts is the deploy date (the pages say 7 October 2026, gap-log G62)
  • The address spelling is confirmed (2026-10-07)
  • abuse@ and postmaster@ pass the outside test (R4) and the un-consented list is gone (G17, G61). Both done 2026-10-26: the 502 imported contacts were deleted rather than revoked, and none had ever been mailed
  • The docs site (handbook.vlozi.app) is behind a login. It is not: it answers without one (checked 2026-10-07), and it serves what is under docs/, which includes the private ops@ address and internal gap descriptions (gap-log G70)

To redeploy after a later change:

$env:CLOUDFLARE_ACCOUNT_ID = "72fe41e9f39ad60cfb6937bb26ab50c3"
cd apps\website
pnpm run build
npx wrangler pages deploy out --project-name=vlozi-website --branch=main --commit-dirty=true

--branch=main is required, or the deploy is a preview. Status of the site itself:

  • Terms, Privacy, Acceptable Use, Anti-Spam, Abuse and Sub-processors pages are live (checked 2026-10-07)
  • The footer carries the operator line and the sitemap lists the new pages (checked 2026-10-07); llms.txt is not checked
  • One sub-processor list, on its own page, linked from Privacy and Security
  • Each page read once against the case text; nothing contradicts it
foreach ($p in 'terms','privacy','acceptable-use','anti-spam','abuse','sub-processors') { curl.exe -sI "https://vlozi.app/$p" | Select-Object -First 1 }

Done on / by / evidence: ______

Site claims still open

Most of the original list (llms files, newsletter product copy, sub-processor list, analytics wording) was fixed and deployed on 2026-10-06 (Cloudflare Pages 79cc17b9). Two rows are not:

Where Claim Status
Newsletter product page "Real-time analytics: open rates, click maps ... no third-party pixel" First-party open and click tracking is built, but its switch (TRACKING_EMIT) is off in production, so the claim is not true until you turn it on. Switch it on, or reword (gap-log G21)
Waitlist and early-access forms "No spam" / "launch updates — no spam" Not false by itself, but the waitlist is single opt-in. Never mail it without a confirmation step

R9 — CloudWatch alarms

AWS console → CloudWatch → Alarms → Create → SES metrics.

  • Reputation.BounceRate: alarm at 4% (warning 2%), notifying an email you read. 2026-10-26: ses-bounce-rate-4pct, Average over 1 hour, >= 0.04, missing data treated as good, notifies SNS topic ses-reputation-alerts. No warning-level alarm
  • Reputation.ComplaintRate: alarm at 0.08% (warning 0.05%), notifying an email you read. 2026-10-26: ses-complaint-rate-0-08pct, threshold >= 0.001 (0.1%), not 0.08%: the console's threshold box keeps three decimal places and turned 0.0008 into 0. 0.1% is where AWS starts reviewing an account (it pauses sending at 0.5%), so the alarm still fires well before a pause. Same topic and settings as the bounce alarm. The name still says 0-08pct; recreating the alarm only to rename it was not worth it
  • The alarm email is your existing private inbox, which does not depend on this platform being up (decided 2026-10-07, gap-log G63), and the SNS email subscription is confirmed (check the inbox). Topic created with the private inbox and the subscription confirmed by the owner, 2026-10-26
  • Screenshot of both alarms in OK state (2026-10-26). The two rate metrics had no data yet (SES publishes them only after real sending; simulator mail does not count), so the alarms were created from the SES Reputation metrics page's "View in CloudWatch" link, not the metric picker. CloudShell refused to start that day: "Your account verification is in progress" (see R2)

Done on / by / evidence: ______

R10 — Case log

  • case-log.md exists and lists the earlier attempts (two submitted and denied, one drafted and never sent), as far as they can be reconstructed
  • Every AWS message from now on is pasted verbatim with the case ID and date. This stays open until the case closes

Done on / by / evidence: file created 2026-10-05


Known gaps a reviewer could find

The full list, with owners, is in gap-log.md ("Open at a glance"). The two that matter for this request:

  • Vlozi's own newsletter list held 502 contacts who never opted in. Deleted 2026-10-26; none had ever been mailed. The list now holds only people who signed up themselves, plus three unsubscribe records (gap-log G17).
  • No content scanning, no tenant ban, no log-retention job. The Privacy page makes no promise that depends on them; they are Phase B items.

Before you press submit

  • All ten gates above are green and dated
  • Every bracketed tag in case-message.md is resolved or its sentence is deleted
  • The text matches the live site, the policies and the DNS today (re-run the R3 and R8 commands)
  • The un-consented newsletter contacts were never mailed from any provider (checked 2026-10-26: 0 campaign sends) and are now deleted
  • You know who answers the case and will check it daily for a week
Communication