hailer 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8cfb76f161f5c19fc25619cf4f8ee00260f72308817757f7dc97c60a6faf5a77
4
- data.tar.gz: 5e02c982a4d7a0f74a3c55ddce1db73c6745a3e5b26e138505177b79bd9fd6f4
3
+ metadata.gz: 00f5d9ebd2dd587d6f2824487642a03c4d9bef5c6047d3f898975199b6c89745
4
+ data.tar.gz: 6580ca42145825de17fa3096eabf5b13d76f863e62a27a6ed86dfe56c4e0e6a7
5
5
  SHA512:
6
- metadata.gz: 1ac351a5ef316733f4ad68a5a8a1d70518280acdf2168d56a2c429c11daf819ddaf139300fc84d13f30fc11e34a7600bf936db951325f43a5eafac47f1adab05
7
- data.tar.gz: 6e523d30652e08ac572d0f3c45f3359e634f008f7e0bd52ee8fbde1f85a43553eff95351651c1553feb7ae53fe70bc9f96abecb732fac42a8c76262351293b15
6
+ metadata.gz: 3c50b744278952684d7b5984eab32a927885c591202be50fd734a44adca9661a2119573888fd954d91a5174294616aa8b40aa4207332864c4c9e26baa0968314
7
+ data.tar.gz: 73455d8ee3c97a0e948c6b9dab75a5f0ea2efdff910417c60f7996d84c197c4c2adc1ffd0ef51de21b3512c55aeab24c00772290f2c244f74e9280b9d191b406
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Rails writes the email. Hailer deals with sending it.
4
4
 
5
- This repository prepares two things at version **0.2.0** (not published yet):
5
+ This repository is two things:
6
6
 
7
7
  - **`hailer` gem** — an ActionMailer adapter, feedback client, and executable
8
8
  launcher. Platform gems bundle the Rust binary. No Ruby AWS SDK or native extension.
@@ -13,11 +13,9 @@ This repository prepares two things at version **0.2.0** (not published yet):
13
13
  ActionMailer → hailer gem → private Mothership route → hailer binary → SES
14
14
  ```
15
15
 
16
- The working tree also implements an **opt-in durable queued adapter**. See
17
- [durable delivery](docs/durable-delivery.md) for ownership, recovery, routing
18
- and operator controls. It is not included in the preserved 0.2 release
19
- candidates. Current-source macOS, ARM64 Linux and x86_64 Linux verification
20
- gates pass locally; this work has not been published or deployed.
16
+ An **opt-in durable queued adapter** sits alongside the default synchronous
17
+ send path. See [durable delivery](docs/durable-delivery.md) for ownership,
18
+ recovery, routing and operator controls.
21
19
 
22
20
  ## Rails
23
21
 
@@ -25,7 +23,6 @@ Requires Ruby 4.0+ and Rails 8.1 or newer within Rails 8.x.
25
23
  Rails main (8.2 alpha) is also exercised in CommonShare. Older releases are not supported.
26
24
 
27
25
  ```ruby
28
- # Gemfile (use path: "/path/to/hailer" while developing)
29
26
  gem "hailer"
30
27
  ```
31
28
 
@@ -98,7 +95,7 @@ SES account/identities must be configured for sending.
98
95
 
99
96
  ### PostgreSQL
100
97
 
101
- PostgreSQL is the **only live backend** in 0.2. Hailer owns a `hailer` schema,
98
+ PostgreSQL is the **only live backend**. Hailer owns a `hailer` schema,
102
99
  not Rails tables. Use a separate database/role where practical:
103
100
 
104
101
  ```sh
@@ -343,6 +340,21 @@ the Emailable account's remaining credits directly; `submit_batch` itself
343
340
  also checks this before submitting and refuses (without ever reaching the
344
341
  server) if the account has none left or fewer than the batch needs.
345
342
 
343
+ ### SES account diagnostics
344
+
345
+ Operator-only, standalone (no Mothership, no docking - same tier as
346
+ `migrate`/`sync-suppressions`), for checking the AWS side of mail delivery
347
+ without ever sending anything:
348
+
349
+ ```sh
350
+ hailer ses-account # quota, reputation, enforcement status
351
+ hailer ses-identities --identities commonshare.com,insights.commonshare.com
352
+ ```
353
+
354
+ `ses-identities` checks each comma-separated identity independently - one
355
+ unverified or nonexistent identity is reported inline (`error`/`code`) and
356
+ never stops the others from reporting.
357
+
346
358
  ## Failure semantics
347
359
 
348
360
  An HTTP 200 means **SES accepted the message**, not that the recipient received
@@ -369,49 +381,14 @@ The SES SDK makes **one send attempt**. AWS throttling/transient failures return
369
381
  IDs carry the explicit unknown-outcome code. None of these responses authorizes
370
382
  an automatic retry of an ambiguous send.
371
383
 
372
- ## Status and migration
373
-
374
- The delivery contract and Hailer-side feedback processing are implemented. CommonShare's
375
- existing sender is the compatibility reference, not a runtime dependency.
376
-
377
- ### Upgrade from 0.1 redb
378
-
379
- 1. Stop all old Hailer processes cleanly. Keep the source file and a backup.
380
- 2. Provision an **empty** Hailer PostgreSQL database and set its URL.
381
- 3. Run `hailer migrate-redb --file /private/path/state.redb`.
382
- 4. Check reported counts, event cursors, and suppression enforcement before
383
- starting 0.2. Keep the source backup; do not restart old writers after cutover.
384
-
385
- Migration opens redb read-only, checks event/dedup mappings and suppression keys,
386
- and copies bounded batches in **one destination transaction**. It preserves
387
- event IDs, sequence values, suppression metadata, and next-cursor continuity.
388
- It rejects missing/corrupt sources and nonempty targets without wiping anything.
389
- An unclean redb file may require recovery with the old version against a backup
390
- before migration. There is no implicit fallback and no dual-write period.
391
-
392
- Before switching an existing app:
393
-
394
- 1. Provision PostgreSQL, run Hailer on a private Mothership bind, check readiness,
395
- and verify real SES delivery using a deliberate test.
396
- 2. Add the gem, set `HAILER_URL`, and remove the app's old delivery-method
397
- override so Hailer's default takes effect.
398
- 3. Subscribe a dedicated SQS queue before exporting and importing existing
399
- suppressions. Let Hailer catch up and verify the event feed.
400
- 4. Keep existing receivers/interceptors until routing, suppression import,
401
- and any provider-neutral app history consumer have been verified.
402
- 5. Only then remove the old sender and AWS-specific feedback handling.
403
-
404
- CommonShare's local 0.2 integration is tested with its real application,
405
- test database, Mothership, the optimized binary from the macOS gem, its installed 0.1 Ruby
406
- client, and a loopback SES fixture. Its existing AWS
407
- receivers remain until the real subscription and suppression cutover is verified.
408
- No deployed AWS routing has been changed.
409
- The current-source queued adapter and dispatcher also pass a CommonShare smoke
410
- using an isolated Bundler Gemfile, real Mothership and loopback SES. No app
411
- Gemfile or production configuration was changed. Its legacy history observer
412
- still needs queued-ownership semantics before opt-in deployment.
413
- Validation/behavior plugins and distributed account-wide quotas remain later
414
- work. No plugin API or provider exactly-once delivery is promised.
384
+ ## Status
385
+
386
+ The delivery contract, Hailer-side feedback processing, domain blocklist,
387
+ impossible-address rejection, address verification, the queued/quarantine
388
+ pipeline, and SES account diagnostics are all implemented and shipped.
389
+ `[queued]`, `[domain_intel]`, `[suppression_sync]`, `[feedback]`, and
390
+ `[email_verification]` ship disabled by default - absent config, not
391
+ missing code.
415
392
 
416
393
  ## Development
417
394
 
@@ -420,8 +397,6 @@ bundle install
420
397
  bundle exec rake
421
398
  HAILER_TEST_DATABASE_URL=postgres://test_user:password@127.0.0.1/hailer_test cargo test --locked
422
399
  cargo fmt --all -- --check
423
- gem build hailer.gemspec --output /tmp/hailer-0.2.0.gem
424
- bundle exec rake native:package
425
400
  ```
426
401
 
427
402
  The Ruby suite exercises real local HTTP exchanges and a booted Rails app.
@@ -446,63 +421,8 @@ It refuses a non-test app database, points the AWS SDK at a loopback fixture,
446
421
  and rolls back application-history changes. It does not change the app's
447
422
  dependency lockfile or send external mail.
448
423
 
449
- `native:package` builds a locked release and writes
450
- `pkg/hailer-0.2.0-<platform>.gem`. Each platform gem contains exactly its host
451
- binary and a version/platform/SHA-256 manifest. The launcher verifies that
452
- manifest before `exec`, preserving arguments, exit status, and signal handling.
453
424
  `HAILER_BINARY` is an explicit, version-checked source-build override; there is
454
425
  no download or PATH fallback.
455
426
 
456
- Build on each supported release host before publishing its artifact. Nothing
457
- in the packaging task publishes a gem.
458
-
459
- ## Linux releases and RubyGems
460
-
461
- The **Linux binary gems** GitHub Actions workflow builds `x86_64-linux-gnu`
462
- and `aarch64-linux-gnu` natively against Debian 13 Trixie (glibc 2.41).
463
- New Trixie-built artifacts target glibc 2.41 or newer, not Bookworm or
464
- Alpine/musl. The preserved older 0.2 candidates retain their original baseline.
465
- Local OrbStack verification uses `test/linux/Dockerfile` for each architecture
466
- and a separate `ruby:4.0-slim-trixie` runtime.
467
- Use a copied checkout in separate per-architecture Docker work volumes; do not
468
- reuse the macOS `target/` or Ruby bundle. Run the locked Ruby tests, release Rust
469
- tests and `native:package` with an isolated PostgreSQL fixture, then install each
470
- gem in its slim runtime and exercise the launcher, migrations and import CLI.
471
- When transferring a macOS snapshot, use `COPYFILE_DISABLE=1 tar --no-xattrs`
472
- so AppleDouble `._*` metadata cannot appear as spurious SQL migrations.
473
-
474
- ```sh
475
- gh workflow run linux-gems.yml --repo seuros/hailer -f tag=v0.2.0
476
- ```
477
-
478
- The workflow checks out the requested release tag, runs the Ruby and Rust
479
- suites against an isolated PostgreSQL 18 service, and installs each binary gem
480
- in a separate slim Debian container. Pushes/PRs also verify the branch without
481
- creating a release or publishing anything; only explicit workflow dispatch
482
- can attach assets to an existing release.
483
- It verifies the installed platform, bundled-binary manifest, executable version,
484
- and PostgreSQL suppression import before attaching either Linux gem to the
485
- existing release. Existing gem assets are never overwritten; `SHA256SUMS` is
486
- updated to cover all release gems.
487
-
488
- Publishing a GitHub release does **not** publish to RubyGems. Like Shuttlebay,
489
- release assets can be fetched and published with Rake:
490
-
491
- ```sh
492
- bundle exec rake gems:fetch
493
- bundle exec rake gems:push_all
494
- # Or select an explicit release:
495
- bundle exec rake 'gems:push_all[v0.2.0]'
496
- ```
497
-
498
- `gems:push_all` fetches fresh assets, checks every archive's SHA-256,
499
- name/version/platform, and publishes only that verified set. It skips
500
- already-published platforms only when RubyGems reports the identical archive
501
- hash, so an interrupted publication can be resumed without replacing artifacts.
502
- `gems:push` is an alias. No release task rebuilds or silently republishes gems.
503
-
504
- RubyGems may require MFA or a suitably scoped API key. Keep credentials out of
505
- the repository. Publishing makes the packaged Ruby code and binaries public,
506
- even when the GitHub repository is private. Once published, Bundler selects
507
- the matching native gem; do not set `force_ruby_platform` in deployment if
508
- you want the bundled executable.
427
+ Bundler selects the matching native platform gem automatically; do not set
428
+ `force_ruby_platform` in deployment if you want the bundled executable.
@@ -1,11 +1,8 @@
1
- # Durable delivery (in development)
1
+ # Durable delivery
2
2
 
3
3
  The queued Ruby interface, PostgreSQL spool and supervised dispatcher are
4
- implemented. CommonShare source-client and installed macOS binary-gem smoke
5
- tests pass. ARM64 and x86_64 Linux release tests, binary packaging and clean slim
6
- Trixie runtime checks also pass in OrbStack (x86_64 under emulation).
7
- Do not enable queued delivery against the existing 0.2 release
8
- candidates or treat this working tree as a published durable-delivery release.
4
+ implemented and shipped (0.3.0+). It is opt-in: absent `[queued]` config,
5
+ Hailer stays on the synchronous send path and none of this runs.
9
6
 
10
7
  ## Opt-in Rails configuration
11
8
 
data/hailer.example.toml CHANGED
@@ -17,8 +17,7 @@ interval_seconds = 3600
17
17
  # recipients_per_second = 10.0
18
18
  # burst = 50
19
19
 
20
- # In development: durable intake requires explicit logical payload budgets.
21
- # Requires the durable-dispatch build, not the existing 0.2 release candidates.
20
+ # Durable intake requires explicit logical payload budgets.
22
21
  # [queued]
23
22
  # max_bytes = 268435456
24
23
  # max_messages = 10000
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hailer
4
- VERSION = '0.3.1'
4
+ VERSION = '0.5.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hailer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih