Skip to content

docs: execute the provider-neutral HayaSend direction - #84

Merged
yhay81 merged 1 commit into
mainfrom
agent/production-cloudflare-execution-plan
Jul 26, 2026
Merged

docs: execute the provider-neutral HayaSend direction#84
yhay81 merged 1 commit into
mainfrom
agent/production-cloudflare-execution-plan

Conversation

@yhay81

@yhay81 yhay81 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Outcome

Turn the accepted direction in #81 into a stage-gated implementation plan: production semantics first, then a provider-neutral Cloudflare proof, controlled FolioMCP dogfood, and only then agent-safe policy.

What changed

  • define ten non-negotiable customer-owned data-plane invariants
  • document the current AWS gaps instead of treating aggregate status and client-triggered dispatch repair as the final model
  • specify canonical message, recipient, attempt, provider-event, and transactional-outbox records
  • define honest at-least-once boundaries and provider-acceptance ambiguity
  • require a versioned provider capability contract and common conformance report
  • add entry criteria, deliverables, exit evidence, and non-goals for five gates
  • ground the Cloudflare proof in current official Email Service, D1, R2, and Queues behavior
  • enumerate eleven focused implementation slices
  • classify all 23 post-v0.1 drafts exactly once as rebase/review, combine into the semantics series, or park
  • align the public roadmap and commercial/support boundary with a content-blind optional management plane

Draft disposition

The plan preserves production-focused work, combines #49/#51/#53 into an ordered semantics series, and parks #33/#55/#77/#82. Existing stacks #59#61 and #73#75 remain ordered.

Post-release refresh

  • HayaSend v0.1.0 is fully released from protected main.
  • The former stacked ancestry was replaced with one GPG-signed plan commit on current main.
  • The PR now changes only README.md, ROADMAP.md, SUPPORT.md, docs/commercial.md, and the new docs/execution-plan.md.
  • No feature draft is included or authorized for premature merge.

Validation

  • npm ci
  • npm run check
  • npm test — 22 files / 146 tests
  • npm run build
  • npm audit --omit=dev --audit-level=high — 0 vulnerabilities
  • npm outdated --depth=0 --json — no direct updates
  • Prettier check for all five changed Markdown files
  • git diff --check
  • signed commit with DCO sign-off

Closes #83
Relates to #81

@yhay81 yhay81 added documentation Improvements or additions to documentation roadmap Accepted public roadmap work labels Jul 26, 2026 — with ChatGPT Codex Connector
Base automatically changed from release/v0.1.0 to main July 26, 2026 12:28
Turn the accepted customer-owned, provider-neutral direction into evidence-gated production semantics, Cloudflare, FolioMCP, and agent-policy work.

Define the transactional outbox and recipient ledger targets, fault and conformance evidence, commercial data boundary, and disposition of every post-v0.1 draft.

Closes #83

Relates to #81

Signed-off-by: Yusuke Hayashi <yusuke8h@gmail.com>
@yhay81
yhay81 force-pushed the agent/production-cloudflare-execution-plan branch from ecab25e to 34b3e19 Compare July 26, 2026 14:54
@yhay81
yhay81 marked this pull request as ready for review July 26, 2026 14:54
@yhay81
yhay81 merged commit 21f79d3 into main Jul 26, 2026
6 checks passed
@yhay81
yhay81 deleted the agent/production-cloudflare-execution-plan branch July 26, 2026 14:56
yhay81 added a commit that referenced this pull request Jul 26, 2026
## Summary

- re-dispatch stored `queued` and `scheduled` emails when an identical
idempotent request is replayed
- preserve the original email ID and stored schedule during recovery
- rely on the existing atomic send lease and final-state checks to
collapse duplicate SQS deliveries
- document the ambiguous-acceptance recovery procedure and at-least-once
boundary

## Root cause

Email persistence and SQS/EventBridge dispatch are separate operations.
If persistence succeeded and dispatch then failed, the API returned an
error but retained the email and idempotency claim. An identical retry
returned that stored record without restoring an immediate or
short-delay job, so the email could remain queued forever.

## Impact

Clients can safely retry the identical payload with the same idempotency
key after an ambiguous API failure. HayaSend returns the same ID and
restores dispatch for eligible non-final records. Replays never
re-dispatch `sending`, canceled, suppressed, or terminal records.

This remains an immediate risk-reduction bridge. The accepted #81/#84
direction replaces client-triggered repair with durable outbox
reconciliation in the provider-neutral semantics series.

## Validation

- `npm ci`
- `npm run check`
- `npm test` — 22 files, 170 tests
- `npm run build`
- `npm run lint:openapi`
- `npm audit --omit=dev --audit-level=high` — 0 vulnerabilities
- `npm outdated --json` — no direct dependency updates available
- `git diff --check`

Closes #50

Signed-off-by: Yusuke Hayashi <yusuke8h@gmail.com>
yhay81 added a commit that referenced this pull request Jul 26, 2026
## Outcome

Publish the first Gate 1 contract from #81/#84: versioned provider
capabilities, generated conformance schemas, and a provider-neutral
fault catalog.

## What changed

- define strict Zod contracts for capability documents, conformance
cases, and evidence reports
- publish the current AWS SES adapter document with effective HayaSend
limits and explicit unsupported capabilities
- generate JSON Schema 2020-12 artifacts and fail CI/release validation
on any drift
- require complete case coverage, consistent totals, matching
provider/version/digest, chronological runs, HTTPS evidence, and
evidence-backed `unsupported`
- include the machine-readable capability and case files in the future
npm package boundary
- document official AWS sources checked on 2026-07-26

## Current truth

- HayaSend limits: 9 MiB serialized request, conservative 39 MiB MIME
estimate, 50 combined recipients, 20 attachments, 25 MiB decoded
attachments, 100 strict batch items, 30-day scheduling
- provider event ID persistence: unsupported until #99
- provider-side send idempotency: unsupported
- message content, addresses, raw provider errors, and credentials
remain outside default evidence

## Validation

- `npm run check`
- `npm run check:conformance`
- `npm test` — 23 files, 175 tests
- `npm run build`
- `npm run lint:openapi`
- `npm audit --omit=dev --audit-level=high` — 0 vulnerabilities
- `npm outdated --json` — no direct updates available
- `actionlint .github/workflows/*.yml`
- `npm pack --dry-run --json` — conformance documents and schemas
included
- `gitleaks protect --staged --redact --no-banner`
- `git diff --check`

Closes #95

Signed-off-by: Yusuke Hayashi <yusuke8h@gmail.com>
yhay81 added a commit that referenced this pull request Jul 26, 2026
## Outcome

Adds the provider-neutral Gate 1 domain contract from #96 without
changing the public API, current stores, or AWS runtime behavior.

- versioned message, recipient, attempt, provider-event, and outbox
records
- opaque recipient and attempt IDs; normalized To/Cc/Bcc roles
- deterministic outbox and provider-event identities with no
address-derived keys
- fixed privacy-safe diagnostic categories and explicit
provider/capability versions
- generated JSON Schema with reproducible generation and CI drift checks
- lifecycle, ambiguity, immutability, and privacy documentation

Closes #96
Parent direction: #81
Execution plan: #84

## Local evidence

- `npm run check`
- `npm run check:conformance`
- `npm test` (24 files, 180 tests)
- `npm run build`
- `npm run lint:openapi`
- `sam validate --lint --template-file template.yaml --region us-east-1`
- `actionlint`
- `npm audit --audit-level=low` (0 vulnerabilities)
- `npm outdated --json` (`{}`)
- `npm pack --dry-run --json`
- `gitleaks git --staged` (no leaks)
- `git diff --check`

Signed-off-by: Yusuke Hayashi <yusuke8h@gmail.com>
yhay81 added a commit that referenced this pull request Jul 26, 2026
## Outcome

Implements the memory-adapter reference semantics for the transactional
outbox in #97, without changing AWS persistence yet.

- atomically copy-on-write commits the sendable email, provider-neutral
message, recipients, optional idempotency claim, and deterministic
outbox item
- validates linkage, pristine state, schedule/due time, unique envelope
recipients, and unexpired idempotency
- conditionally leases due items with exact expiry recovery and one
active owner
- publishes stable `job_id` values, acknowledges dispatch, and safely
retries queue failures
- preserves the same job identity after queue-acceptance ambiguity
- supports continuous sweeps with AbortSignal shutdown
- exposes privacy-safe due, leased, undispatched, oldest-age, and
failure counters
- injects failures at every staged commit/write and queue boundary

Closes #97
Parent direction: #81
Execution plan: #84

## Local evidence

- `npm run check`
- `npm run check:conformance`
- `npm test` (25 files, 201 tests; 21 focused outbox tests)
- `npm run build`
- `npm run lint:openapi`
- `sam validate --lint --template-file template.yaml --region us-east-1`
- `actionlint`
- `npm audit --audit-level=low` (0 vulnerabilities)
- `npm outdated --json` (`{}`)
- `npm pack --dry-run --json` (new port and reconciler included)
- `gitleaks git --staged` (no leaks)
- `git diff --check`

Signed-off-by: Yusuke Hayashi <yusuke8h@gmail.com>
yhay81 added a commit that referenced this pull request Jul 27, 2026
Implements #100 under the accepted direction in #81 and the execution
order in #84.

## What changes

- adds `GET /emails/{id}/recipients` and `hayasend emails recipients ID`
with opaque IDs, stable pagination, deterministic recipient-derived
aggregate status, attempt state, ambiguity/retry state, and allowlisted
output
- adds `GET /diagnostics/recovery`, protected by the new
`diagnostics:read` scope, for outbox age/stuck leases, SQS and DLQ
depth, provider-event lag, and provider capability digest
- makes `doctor` report recovery availability and compare the running
AWS capability digest to the installed CLI without breaking keys that
lack `diagnostics:read`
- records the latest provider-event timestamp in MemoryStore and
DynamoDB without allowing older out-of-order evidence to regress it
- grants the API Lambda only `sqs:GetQueueAttributes` on its stack-owned
queues
- documents the privacy and authorization boundary in OpenAPI, CLI,
operations, README, changelog, and the conformance catalog
- updates `@redocly/cli` from 2.40.0 to 2.41.0

Default API and CLI output never includes addresses, subjects, bodies,
credentials, signed URLs, provider message IDs, raw provider errors,
queue URLs, or unrecognized fields.

## Current-head local evidence

Rebased signed head: `c7c493603e70002a567ff9c0e66e448baa9dad7e`

- `npm test` — 39 files / 361 tests passed
- `npm run check`
- `npm run check:conformance`
- `npm run build`
- `npm audit --audit-level=low` — 0 vulnerabilities
- `npm outdated --json` — empty
- `git diff --check`
- both rebased commits have valid GPG signatures and Signed-off-by
trailers

The only tree changes introduced by refreshing the previously AWS-tested
head onto current `main` are the independently merged npm
release-recovery workflow and its tests
(`.github/workflows/release.yml`, `tests/npm-package.test.ts`).

## AWS product evidence

Application head `e9514d4dc4f636425a8a9db8327331c519fe2915`:

- [AWS integration run
30256105349](https://github.com/haya-inc/hayasend/actions/runs/30256105349)
passed in the dedicated empty `hayainc-test` account with
`retain_stack=false`
- proved scoped 403 boundaries, two-recipient opaque pagination, privacy
allowlists, outbox metrics, SQS and delivery/scheduler DLQ depths,
disabled inbound DLQ, AWS SES capability digest, durable outbox
recovery, and complete stack/resource cleanup
- temporary exact-branch environment allowance was removed;
`aws-integration` again permits only `main`

## Release gate

[v0.2.0](https://github.com/haya-inc/hayasend/releases/tag/v0.2.0) is
fully published and verified, so the former post-release Draft gate is
satisfied. No review or work is requested from `nurazon59`.

---------

Signed-off-by: Yusuke Hayashi <yusuke8h@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation roadmap Accepted public roadmap work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Publish the production-semantics and Cloudflare proof execution plan

1 participant