hecks 3.7.0 → 3.9.1

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/bluebook/meta_validator/modes.rb +14 -0
  3. data/lib/hecks/bluebook/meta_validator.rb +4 -2
  4. data/lib/hecks/corpus/routes.rb +1 -1
  5. data/lib/hecks/gate/stages.yml +11 -1
  6. data/lib/hecks/hecks/adapters/site_toolchain/prober.rb +64 -0
  7. data/lib/hecks/hecks/adapters/site_toolchain.rb +41 -5
  8. data/lib/hecks/language/bluebook/vocabulary.bluebook +1 -1
  9. data/lib/hecks/projections/deploy/shared_database_instance/templates/rds.yaml.tmpl +1 -1
  10. data/lib/hecks/projections/deploy/templates/lambda/template.yaml.tmpl +1 -1
  11. data/lib/hecks/projections/site/probe.rb +131 -0
  12. data/lib/hecks/projections/site/site_host/dockerfile.rb +1 -1
  13. data/lib/hecks/runtime/value/validation.rb +34 -3
  14. data/lib/hecks/site/bluebook/site.bluebook +31 -0
  15. data/lib/hecks/site/bluebook/site.ports.hecksagon +6 -0
  16. data/lib/hecks/version.rb +1 -1
  17. data/lib/hecks/vocabulary.rb +1 -1
  18. data/prebuilt/{verdicts-be73f0df9eee0abe2f4aadc968321c4b919d19d424a3ccfe1777a71dabf7d9e7.json → verdicts-91aaf93ce8981bd9a754948f075d95650dc2ec6435015376f5c60992b36a24b1.json} +1 -1
  19. data/rust/codegen/src/fielded.rs +3 -3
  20. data/rust/codegen/src/json_codec.rs +2 -2
  21. data/rust/codegen/src/naming.rs +20 -0
  22. data/rust/host/Cargo.toml +4 -0
  23. data/rust/host/HECKS_RELEASE +1 -1
  24. data/rust/host/src/boot.rs +443 -0
  25. data/rust/host/src/boundary_fuzz/ir.rs +1 -0
  26. data/rust/host/src/commerce_ir.rs +459 -0
  27. data/rust/host/src/extension.rs +100 -0
  28. data/rust/host/src/ir.rs +0 -448
  29. data/rust/host/src/journal.rs +1 -1
  30. data/rust/host/src/lib.rs +40 -0
  31. data/rust/host/src/main.rs +4 -477
  32. data/rust/host/src/mint.rs +1 -1
  33. data/rust/host/src/payments/tests.rs +8 -8
  34. data/rust/host/src/payments.rs +10 -10
  35. data/rust/host/src/rate_limit.rs +27 -41
  36. data/rust/host/src/secrets.rs +15 -0
  37. data/rust/host/src/web/commerce.rs +121 -0
  38. data/rust/host/src/web/newsletter.rs +2 -1
  39. data/rust/host/src/web/newsletter_send.rs +1 -1
  40. data/rust/host/src/web/registration_receipt.rs +2 -2
  41. data/rust/host/src/web/registrations.rs +49 -49
  42. data/rust/host/src/web/resend_webhook.rs +300 -0
  43. data/rust/host/src/web.rs +43 -47
  44. metadata +13 -5
  45. /data/prebuilt/{a0818e2de67364dc1ab22868b6cbf869c62da6f8d9b924c778fa5cce2e76ee94.marshal → 0ee7f83cba59ce7d1c45c65ba166b071779f70143449f584f33ff7989f64eccb.marshal} +0 -0
  46. /data/prebuilt/{945481eefbdb584649d45f256307053558966a868b9c38dee7ee88f8169610f8.marshal → 6e4a6bcf0aa880e2e6b056e1846b70e5a768090b9dc998bbadeaf5d6bcfd3db8.marshal} +0 -0
@@ -1,7 +1,7 @@
1
1
  use super::{instances_for, last_refusal, respond, with_id};
2
2
  use crate::checkout;
3
3
  use crate::dispatch;
4
- use crate::ir::{payments_provider, PaymentsProvider};
4
+ use crate::commerce_ir::{payments_provider, PaymentsProvider};
5
5
  use crate::journal::LineageConfig;
6
6
  use crate::lambda_client::LambdaInvoker;
7
7
  use crate::payments;
@@ -15,7 +15,7 @@ use tokio_postgres::Client;
15
15
 
16
16
  /// Whether checkout is on: `configured` must be set and equal `domain`
17
17
  /// exactly — a mismatch would dispatch the wrong domain's Registration.Request.
18
- pub(crate) fn checkout_enabled(configured: Option<&str>, domain: &str) -> bool {
18
+ pub fn checkout_enabled(configured: Option<&str>, domain: &str) -> bool {
19
19
  configured.is_some_and(|c| !c.is_empty() && c == domain)
20
20
  }
21
21
 
@@ -63,7 +63,7 @@ fn seat_counts(read: &Value, domain: &str, payments: &PaymentsProvider) -> std::
63
63
  .filter_map(|(id, payment)| payment.get("status").and_then(|s| s.as_str()).map(|s| (id, s.to_string())))
64
64
  .collect();
65
65
  let mut counts = std::collections::HashMap::new();
66
- for (id, registration) in instances_for(read, &crate::ir::registrations_binding(domain).registration_prefix()) {
66
+ for (id, registration) in instances_for(read, &crate::commerce_ir::registrations_binding(domain).registration_prefix()) {
67
67
  let holds = statuses.get(&id).is_some_and(|status| SEAT_HOLDING_PAYMENT_STATUSES.contains(&status.as_str()));
68
68
  if let (true, false, Some(event_slug)) = (holds, registration_archived(&registration), plain_id(registration.get("event_slug"))) {
69
69
  *counts.entry(event_slug).or_insert(0) += 1;
@@ -90,7 +90,7 @@ fn open_seats(capacity: i64, taken: usize) -> i64 {
90
90
  /// Seats still open on one event, never below zero; `None` when there is no
91
91
  /// such event or it carries no readable capacity.
92
92
  pub(crate) fn seats_left(read: &Value, domain: &str, payments: &PaymentsProvider, event_slug: &str) -> Option<i64> {
93
- let events = instances_for(read, &crate::ir::registrations_binding(domain).event_prefix());
93
+ let events = instances_for(read, &crate::commerce_ir::registrations_binding(domain).event_prefix());
94
94
  let (_, event) = events.iter().find(|(id, _)| id == event_slug)?;
95
95
  Some(open_seats(event_capacity(event)?, seats_taken(read, domain, payments, event_slug)))
96
96
  }
@@ -105,7 +105,7 @@ fn seat_figures(event: &Value, taken: usize) -> Value {
105
105
  /// The seat figures of every event, keyed by event slug.
106
106
  fn all_seat_figures(read: &Value, domain: &str, payments: &PaymentsProvider) -> Value {
107
107
  let counts = seat_counts(read, domain, payments);
108
- let events = instances_for(read, &crate::ir::registrations_binding(domain).event_prefix());
108
+ let events = instances_for(read, &crate::commerce_ir::registrations_binding(domain).event_prefix());
109
109
  let figures: serde_json::Map<String, Value> =
110
110
  events.iter().map(|(slug, event)| (slug.clone(), seat_figures(event, counts.get(slug).copied().unwrap_or(0)))).collect();
111
111
  json!({"events": figures})
@@ -113,7 +113,7 @@ fn all_seat_figures(read: &Value, domain: &str, payments: &PaymentsProvider) ->
113
113
 
114
114
  /// The seat figures of one event, with its `slug`; `None` when there is no such event.
115
115
  fn one_seat_figures(read: &Value, domain: &str, payments: &PaymentsProvider, event_slug: &str) -> Option<Value> {
116
- let events = instances_for(read, &crate::ir::registrations_binding(domain).event_prefix());
116
+ let events = instances_for(read, &crate::commerce_ir::registrations_binding(domain).event_prefix());
117
117
  let (_, event) = events.iter().find(|(id, _)| id == event_slug)?;
118
118
  let mut figures = seat_figures(event, seats_taken(read, domain, payments, event_slug));
119
119
  figures["slug"] = json!(event_slug);
@@ -224,7 +224,7 @@ async fn events_route(raw_body: &str, client: &Mutex<Client>, wasm_path: &Path,
224
224
  Ok(r) => r,
225
225
  Err(e) => return respond(500, "text/plain", &format!("{e:#}")),
226
226
  };
227
- let events = instances_for(&read, &crate::ir::registrations_binding(&config.domain).event_prefix());
227
+ let events = instances_for(&read, &crate::commerce_ir::registrations_binding(&config.domain).event_prefix());
228
228
  if let Some((_, existing)) = events.iter().find(|(id, _)| id == slug) {
229
229
  return respond(200, "application/json", &serde_json::to_string_pretty(&with_id(slug, existing)).unwrap_or_default());
230
230
  }
@@ -245,7 +245,7 @@ async fn events_route(raw_body: &str, client: &Mutex<Client>, wasm_path: &Path,
245
245
  "price": {"cents": price_cents},
246
246
  "capacity": {"value": capacity},
247
247
  });
248
- let verb = crate::ir::registrations_binding(&config.domain).schedule;
248
+ let verb = crate::commerce_ir::registrations_binding(&config.domain).schedule;
249
249
  let outcome = match dispatch::handle(client, wasm_path, &verb, args, None, config, invoker).await {
250
250
  Ok(o) => o,
251
251
  Err(e) => return respond(500, "text/plain", &format!("{e:#}")),
@@ -258,7 +258,7 @@ async fn events_route(raw_body: &str, client: &Mutex<Client>, wasm_path: &Path,
258
258
  Ok(r) => r,
259
259
  Err(e) => return respond(500, "text/plain", &format!("{e:#}")),
260
260
  };
261
- let events = instances_for(&read, &crate::ir::registrations_binding(&config.domain).event_prefix());
261
+ let events = instances_for(&read, &crate::commerce_ir::registrations_binding(&config.domain).event_prefix());
262
262
  let Some((_, event)) = events.iter().find(|(id, _)| id == slug) else {
263
263
  return respond(500, "text/plain", "event vanished immediately after being scheduled");
264
264
  };
@@ -272,12 +272,12 @@ async fn registration_show_route(registration_id: &str, client: &Mutex<Client>,
272
272
  Ok(r) => r,
273
273
  Err(e) => return respond(500, "text/plain", &format!("{e:#}")),
274
274
  };
275
- let registrations = instances_for(&read, &crate::ir::registrations_binding(&config.domain).registration_prefix());
275
+ let registrations = instances_for(&read, &crate::commerce_ir::registrations_binding(&config.domain).registration_prefix());
276
276
  let Some((_, registration)) = registrations.iter().find(|(id, _)| id == registration_id) else {
277
277
  return respond(404, "application/json", &json!({"error": "no such registration"}).to_string());
278
278
  };
279
279
  let event_slug = registration.get("event_slug").and_then(|v| v.as_str());
280
- let events = instances_for(&read, &crate::ir::registrations_binding(&config.domain).event_prefix());
280
+ let events = instances_for(&read, &crate::commerce_ir::registrations_binding(&config.domain).event_prefix());
281
281
  let event = event_slug.and_then(|slug| events.iter().find(|(id, _)| id == slug)).map(|(_, e)| e);
282
282
 
283
283
  let payment_instances = instances_for(&read, &payments.instance_prefix());
@@ -327,7 +327,7 @@ pub(crate) async fn registration_complete_route(
327
327
  Ok(r) => r,
328
328
  Err(e) => return respond(500, "text/plain", &format!("{e:#}")),
329
329
  };
330
- let registrations = instances_for(&read, &crate::ir::registrations_binding(&config.domain).registration_prefix());
330
+ let registrations = instances_for(&read, &crate::commerce_ir::registrations_binding(&config.domain).registration_prefix());
331
331
  if !registrations.iter().any(|(id, _)| id == registration_id) {
332
332
  return respond(404, "application/json", &json!({"error": "no such registration"}).to_string());
333
333
  }
@@ -441,7 +441,7 @@ pub(crate) async fn registrations_route(
441
441
  Ok(r) => r,
442
442
  Err(e) => return respond(500, "text/plain", &format!("{e:#}")),
443
443
  };
444
- let events = instances_for(&read, &crate::ir::registrations_binding(&config.domain).event_prefix());
444
+ let events = instances_for(&read, &crate::commerce_ir::registrations_binding(&config.domain).event_prefix());
445
445
  let Some((_, event)) = events.iter().find(|(id, _)| id == event_slug) else {
446
446
  return respond(404, "application/json", &json!({"error": "no such event"}).to_string());
447
447
  };
@@ -518,9 +518,9 @@ pub(crate) async fn registrations_route(
518
518
  // inside `attendee`, so newsletter fields are declared flat on
519
519
  // Registration.Request; a command refuses args it doesn't declare.
520
520
  let news_signup = body.get("news_signup").and_then(|v| v.as_bool()).unwrap_or(false);
521
- let binding = crate::ir::registrations_binding(&config.domain);
521
+ let binding = crate::commerce_ir::registrations_binding(&config.domain);
522
522
  let forwards_newsletter = crate::ir::ir().is_some_and(|ir| {
523
- binding.request_target().is_some_and(|(aggregate, command)| crate::ir::command_declares(ir, aggregate, command, "news_signup"))
523
+ binding.request_target().is_some_and(|(aggregate, command)| crate::commerce_ir::command_declares(ir, aggregate, command, "news_signup"))
524
524
  });
525
525
  if forwards_newsletter {
526
526
  request_args["news_signup"] = json!(news_signup);
@@ -531,7 +531,7 @@ pub(crate) async fn registrations_route(
531
531
  }
532
532
  }
533
533
  }
534
- let request_verb = crate::ir::registrations_binding(&config.domain).request;
534
+ let request_verb = crate::commerce_ir::registrations_binding(&config.domain).request;
535
535
  let outcome = match dispatch::handle(client, wasm_path, &request_verb, request_args, None, config, invoker).await {
536
536
  Ok(o) => o,
537
537
  Err(e) => return respond(500, "text/plain", &format!("{e:#}")),
@@ -749,7 +749,7 @@ mod tests {
749
749
 
750
750
  #[test]
751
751
  fn a_registration_holds_a_seat_while_its_payment_is_open_paid_or_being_settled() {
752
- let payments = crate::ir::fixture_payments();
752
+ let payments = crate::commerce_ir::fixture_payments();
753
753
  let read = read_with(
754
754
  10,
755
755
  &[("a", "yoga", "pending"), ("b", "yoga", "succeeded"), ("c", "yoga", "refunding"), ("d", "yoga", "disputed")],
@@ -760,7 +760,7 @@ mod tests {
760
760
 
761
761
  #[test]
762
762
  fn a_failed_refunded_or_charged_back_payment_gives_its_seat_back() {
763
- let payments = crate::ir::fixture_payments();
763
+ let payments = crate::commerce_ir::fixture_payments();
764
764
  let read = read_with(
765
765
  3,
766
766
  &[("a", "yoga", "failed"), ("b", "yoga", "refunded"), ("c", "yoga", "charged_back"), ("d", "yoga", "succeeded")],
@@ -771,7 +771,7 @@ mod tests {
771
771
 
772
772
  #[test]
773
773
  fn seats_are_counted_per_event_and_a_registration_without_a_payment_holds_none() {
774
- let payments = crate::ir::fixture_payments();
774
+ let payments = crate::commerce_ir::fixture_payments();
775
775
  let mut read = read_with(4, &[("a", "yoga", "succeeded"), ("b", "other", "succeeded")]);
776
776
  read["instances"]["CheckoutFixture::Registration#orphan"] = json!({"event_slug": "yoga"});
777
777
  assert_eq!(seats_taken(&read, "CheckoutFixture", &payments, "yoga"), 1, "only this event's registrations, and only those with a payment");
@@ -780,7 +780,7 @@ mod tests {
780
780
 
781
781
  #[test]
782
782
  fn an_archived_registration_gives_its_seat_back_whatever_its_payment_says() {
783
- let payments = crate::ir::fixture_payments();
783
+ let payments = crate::commerce_ir::fixture_payments();
784
784
  let mut read = read_with(3, &[("a", "yoga", "succeeded"), ("b", "yoga", "pending"), ("c", "yoga", "succeeded")]);
785
785
  assert_eq!(seats_taken(&read, "CheckoutFixture", &payments, "yoga"), 3);
786
786
  read["instances"]["CheckoutFixture::Registration#a"]["status"] = json!("archived");
@@ -790,7 +790,7 @@ mod tests {
790
790
 
791
791
  #[test]
792
792
  fn a_registration_with_no_status_counts_as_active() {
793
- let payments = crate::ir::fixture_payments();
793
+ let payments = crate::commerce_ir::fixture_payments();
794
794
  let mut read = read_with(5, &[("a", "yoga", "succeeded"), ("b", "yoga", "succeeded")]);
795
795
  // `a` carries no status at all (a domain without the lifecycle, or data
796
796
  // from before it existed); `b` says it is active.
@@ -802,7 +802,7 @@ mod tests {
802
802
 
803
803
  #[test]
804
804
  fn a_restored_registration_takes_its_seat_back() {
805
- let payments = crate::ir::fixture_payments();
805
+ let payments = crate::commerce_ir::fixture_payments();
806
806
  let mut read = read_with(2, &[("a", "yoga", "succeeded")]);
807
807
  read["instances"]["CheckoutFixture::Registration#a"]["status"] = json!("archived");
808
808
  assert_eq!(seats_left(&read, "CheckoutFixture", &payments, "yoga"), Some(2));
@@ -812,7 +812,7 @@ mod tests {
812
812
 
813
813
  #[test]
814
814
  fn seats_left_with_mixed_statuses_counts_only_the_active_holders() {
815
- let payments = crate::ir::fixture_payments();
815
+ let payments = crate::commerce_ir::fixture_payments();
816
816
  let mut read = read_with(
817
817
  6,
818
818
  &[("a", "yoga", "succeeded"), ("b", "yoga", "succeeded"), ("c", "yoga", "pending"), ("d", "yoga", "failed"), ("e", "other", "succeeded")],
@@ -830,7 +830,7 @@ mod tests {
830
830
 
831
831
  #[test]
832
832
  fn seats_left_never_goes_below_zero_and_is_none_without_an_event_or_capacity() {
833
- let payments = crate::ir::fixture_payments();
833
+ let payments = crate::commerce_ir::fixture_payments();
834
834
  let oversold = read_with(1, &[("a", "yoga", "succeeded"), ("b", "yoga", "succeeded")]);
835
835
  assert_eq!(seats_left(&oversold, "CheckoutFixture", &payments, "yoga"), Some(0));
836
836
  assert_eq!(seats_left(&oversold, "CheckoutFixture", &payments, "nowhere"), None);
@@ -858,7 +858,7 @@ mod tests {
858
858
 
859
859
  #[test]
860
860
  fn every_holding_status_holds_one_seat_and_every_freeing_status_holds_none() {
861
- let payments = crate::ir::fixture_payments();
861
+ let payments = crate::commerce_ir::fixture_payments();
862
862
  for status in HOLDING {
863
863
  let read = read_with(10, &[("r", "yoga", status)]);
864
864
  assert_eq!(seats_taken(&read, "CheckoutFixture", &payments, "yoga"), 1, "{status} should hold a seat");
@@ -871,7 +871,7 @@ mod tests {
871
871
 
872
872
  #[test]
873
873
  fn a_reference_reads_as_a_plain_id_or_a_wrapped_value_and_counts_per_event() {
874
- let payments = crate::ir::fixture_payments();
874
+ let payments = crate::commerce_ir::fixture_payments();
875
875
  let mut read = read_with(
876
876
  10,
877
877
  &[("a", "yoga", "succeeded"), ("b", "yoga", "pending"), ("c", "other", "pending"), ("d", "yoga", "failed")],
@@ -885,7 +885,7 @@ mod tests {
885
885
 
886
886
  #[test]
887
887
  fn a_payment_with_no_registration_is_ignored_and_a_missing_or_empty_read_counts_nothing() {
888
- let payments = crate::ir::fixture_payments();
888
+ let payments = crate::commerce_ir::fixture_payments();
889
889
  let mut read = read_with(5, &[]);
890
890
  read["instances"]["CheckoutFixture::Registration#lonely"] = json!({"event_slug": "yoga"});
891
891
  read["instances"]["Payments::Payment#orphan"] = json!({"status": "succeeded"});
@@ -898,7 +898,7 @@ mod tests {
898
898
 
899
899
  #[test]
900
900
  fn an_archived_registration_frees_its_seat_whichever_holding_status_its_payment_has() {
901
- let payments = crate::ir::fixture_payments();
901
+ let payments = crate::commerce_ir::fixture_payments();
902
902
  for status in HOLDING {
903
903
  let mut read = read_with(10, &[("r", "yoga", status)]);
904
904
  set_registration_status(&mut read, "r", "archived");
@@ -908,7 +908,7 @@ mod tests {
908
908
 
909
909
  #[test]
910
910
  fn archiving_one_of_several_guests_frees_exactly_one_seat() {
911
- let payments = crate::ir::fixture_payments();
911
+ let payments = crate::commerce_ir::fixture_payments();
912
912
  let mut read = read_with(10, &[("a", "yoga", "succeeded"), ("b", "yoga", "succeeded"), ("c", "yoga", "pending")]);
913
913
  set_registration_status(&mut read, "a", "active");
914
914
  set_registration_status(&mut read, "b", "archived");
@@ -918,7 +918,7 @@ mod tests {
918
918
 
919
919
  #[test]
920
920
  fn seat_figures_carry_capacity_taken_and_left_and_null_without_a_capacity() {
921
- let payments = crate::ir::fixture_payments();
921
+ let payments = crate::commerce_ir::fixture_payments();
922
922
  let read = read_with(3, &[("a", "yoga", "succeeded"), ("b", "yoga", "pending"), ("c", "yoga", "succeeded"), ("d", "yoga", "succeeded")]);
923
923
  assert_eq!(one_seat_figures(&read, "CheckoutFixture", &payments, "yoga"), Some(json!({"slug": "yoga", "capacity": 3, "seats_taken": 4, "seats_left": 0})));
924
924
  assert_eq!(one_seat_figures(&read, "CheckoutFixture", &payments, "nowhere"), None);
@@ -938,7 +938,7 @@ mod tests {
938
938
 
939
939
  #[test]
940
940
  fn the_seat_figures_agree_with_seats_left_for_every_event() {
941
- let payments = crate::ir::fixture_payments();
941
+ let payments = crate::commerce_ir::fixture_payments();
942
942
  let mut read = read_with(6, &[("a", "yoga", "succeeded"), ("b", "yoga", "refunding"), ("c", "other", "pending"), ("d", "yoga", "failed")]);
943
943
  set_registration_status(&mut read, "b", "archived");
944
944
  let all = all_seat_figures(&read, "CheckoutFixture", &payments);
@@ -963,7 +963,7 @@ mod tests {
963
963
  let config = checkout_config(1);
964
964
  let wasm_path = checkout_wasm_path();
965
965
  schedule_event(&client, &wasm_path, &config, "yoga", 4200).await;
966
- let ir = crate::ir::fixture_ir();
966
+ let ir = crate::commerce_ir::fixture_ir();
967
967
  let get = |path: &'static str| {
968
968
  let (client, wasm_path, config, ir) = (&client, &wasm_path, &config, &ir);
969
969
  async move {
@@ -1045,7 +1045,7 @@ mod tests {
1045
1045
  let client = scratch_db("hecks_host_web_test_registrations_missing_fields").await;
1046
1046
  provision_lineage(&*client.lock().await, "CheckoutFixture", 1, &["Event", "Registration", "Payment"]).await;
1047
1047
 
1048
- let response = registrations_route(r#"{"event_slug":"yoga-aug"}"#, &payments::test_platform(), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1048
+ let response = registrations_route(r#"{"event_slug":"yoga-aug"}"#, &payments::test_platform(), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1049
1049
  assert_eq!(response["statusCode"], 400);
1050
1050
  assert!(response["body"].as_str().unwrap().contains("missing name"));
1051
1051
  }
@@ -1069,7 +1069,7 @@ mod tests {
1069
1069
  "email": "ada@example.com",
1070
1070
  })
1071
1071
  .to_string();
1072
- let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1072
+ let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1073
1073
 
1074
1074
  // Registration.Request refuses (no first_name/last_name in this
1075
1075
  // Attendee) but only after Payment.Initiate already ran, proving
@@ -1117,7 +1117,7 @@ mod tests {
1117
1117
  }
1118
1118
  }
1119
1119
 
1120
- let fixture_ir = crate::ir::fixture_ir();
1120
+ let fixture_ir = crate::commerce_ir::fixture_ir();
1121
1121
  let response = payments_routes(Some(&fixture_ir), "POST", "/registrations", "not json", "", &client, &wasm_path, &config, &lambda_client::NeverInvoker).await;
1122
1122
  assert_eq!(response.expect("the fixture IR declares payments, so the route answers")["statusCode"], 400);
1123
1123
  }
@@ -1127,7 +1127,7 @@ mod tests {
1127
1127
  let client = scratch_db("hecks_host_web_test_registrations_bad_json").await;
1128
1128
  provision_lineage(&*client.lock().await, "CheckoutFixture", 1, &["Event", "Registration", "Payment"]).await;
1129
1129
 
1130
- let response = registrations_route("not json", &payments::test_platform(), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1130
+ let response = registrations_route("not json", &payments::test_platform(), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1131
1131
  assert_eq!(response["statusCode"], 400);
1132
1132
  }
1133
1133
 
@@ -1212,7 +1212,7 @@ mod tests {
1212
1212
  provision_lineage(&*client.lock().await, "CheckoutFixture", 1, &["Event", "Registration", "Payment"]).await;
1213
1213
 
1214
1214
  let body = json!({"event_slug": "nope", "name": "Ada", "email": "ada@example.com"}).to_string();
1215
- let response = registrations_route(&body, &payments::test_platform(), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1215
+ let response = registrations_route(&body, &payments::test_platform(), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1216
1216
  assert_eq!(response["statusCode"], 404);
1217
1217
  }
1218
1218
 
@@ -1230,7 +1230,7 @@ mod tests {
1230
1230
  assert!(close.accepted, "closing the fixture event should succeed: {:?}", close.result);
1231
1231
 
1232
1232
  let body = json!({"event_slug": "closed-event", "name": "Ada", "email": "ada@example.com"}).to_string();
1233
- let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1233
+ let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1234
1234
  assert_eq!(response["statusCode"], 422);
1235
1235
  assert!(response["body"].as_str().unwrap().contains("closed"));
1236
1236
  }
@@ -1248,7 +1248,7 @@ mod tests {
1248
1248
  schedule_event(&client, &wasm_path, &config, "free-event", 0).await;
1249
1249
 
1250
1250
  let body = json!({"event_slug": "free-event", "name": "Ada", "email": "ada@example.com"}).to_string();
1251
- let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1251
+ let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1252
1252
  assert_eq!(response["statusCode"], 422);
1253
1253
  assert!(
1254
1254
  response["body"].as_str().unwrap().contains("positive"),
@@ -1275,7 +1275,7 @@ mod tests {
1275
1275
  // a misconfiguration — the whole chain runs and returns a real
1276
1276
  // checkout URL, never a 500.
1277
1277
  let body = json!({"event_slug": "happy-event", "name": "Ada Lovelace", "email": "ada@example.com"}).to_string();
1278
- let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1278
+ let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1279
1279
  assert_eq!(response["statusCode"], 200, "{response:?}");
1280
1280
  let body: Value = serde_json::from_str(response["body"].as_str().unwrap()).unwrap();
1281
1281
  let reference = body["registration_id"].as_str().unwrap().to_string();
@@ -1330,7 +1330,7 @@ mod tests {
1330
1330
  "return_to": "/sample-studio.html",
1331
1331
  })
1332
1332
  .to_string();
1333
- let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1333
+ let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1334
1334
  assert_eq!(response["statusCode"], 200, "{response:?}");
1335
1335
  let body: Value = serde_json::from_str(response["body"].as_str().unwrap()).unwrap();
1336
1336
  let reference = body["registration_id"].as_str().unwrap().to_string();
@@ -1361,7 +1361,7 @@ mod tests {
1361
1361
  "return_to": unsafe_return_to,
1362
1362
  })
1363
1363
  .to_string();
1364
- let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1364
+ let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1365
1365
  assert_eq!(response["statusCode"], 200, "{response:?}");
1366
1366
  let body: Value = serde_json::from_str(response["body"].as_str().unwrap()).unwrap();
1367
1367
  // checkout_url is the /pay/<id>.html walkthrough page; return_to
@@ -1390,7 +1390,7 @@ mod tests {
1390
1390
  schedule_event(&client, &wasm_path, &config, "mock-loop-event", 4200).await;
1391
1391
 
1392
1392
  let body = json!({"event_slug": "mock-loop-event", "name": "Ada Lovelace", "email": "ada@example.com"}).to_string();
1393
- let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1393
+ let response = registrations_route(&body, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1394
1394
  assert_eq!(response["statusCode"], 200, "{response:?}");
1395
1395
  let response_body: Value = serde_json::from_str(response["body"].as_str().unwrap()).unwrap();
1396
1396
  let reference = response_body["registration_id"].as_str().unwrap().to_string();
@@ -1403,7 +1403,7 @@ mod tests {
1403
1403
  let now = now_secs();
1404
1404
  let header = sign_stripe_header(secret, now, &payload);
1405
1405
 
1406
- let response = webhook_route(&payload, &header, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1406
+ let response = webhook_route(&payload, &header, &payments::test_platform(), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1407
1407
  assert_eq!(response["statusCode"], 200, "{response:?}");
1408
1408
 
1409
1409
  let read = dispatch::read(&client, &wasm_path).await.unwrap();
@@ -1420,7 +1420,7 @@ mod tests {
1420
1420
  let payload = json!({"type": "checkout.session.completed", "data": {"object": {}}}).to_string();
1421
1421
  let bad_header = "t=1700000000,v1=deadbeef";
1422
1422
 
1423
- let response = webhook_route(&payload, bad_header, &payments::test_platform_with_secret("whsec_test_bad_sig"), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1423
+ let response = webhook_route(&payload, bad_header, &payments::test_platform_with_secret("whsec_test_bad_sig"), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1424
1424
  assert_eq!(response["statusCode"], 400);
1425
1425
  }
1426
1426
 
@@ -1451,7 +1451,7 @@ mod tests {
1451
1451
  let now = now_secs();
1452
1452
  let header = sign_stripe_header(secret, now, &payload);
1453
1453
 
1454
- let response = webhook_route(&payload, &header, &payments::test_platform_with_secret(secret), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1454
+ let response = webhook_route(&payload, &header, &payments::test_platform_with_secret(secret), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1455
1455
  assert_eq!(response["statusCode"], 200, "{response:?}");
1456
1456
 
1457
1457
  let read = dispatch::read(&client, &wasm_path).await.unwrap();
@@ -1462,7 +1462,7 @@ mod tests {
1462
1462
  // A redelivered webhook (Stripe's delivery is at-least-once) for an
1463
1463
  // already-succeeded payment must still answer 200 — the refusal
1464
1464
  // underneath is a benign no-op, not surfaced as an error.
1465
- let redelivered = webhook_route(&payload, &header, &payments::test_platform_with_secret(secret), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1465
+ let redelivered = webhook_route(&payload, &header, &payments::test_platform_with_secret(secret), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1466
1466
  assert_eq!(redelivered["statusCode"], 200, "a redelivered webhook must not surface the resulting refusal as an error: {redelivered:?}");
1467
1467
  }
1468
1468
 
@@ -1492,7 +1492,7 @@ mod tests {
1492
1492
  let now = now_secs();
1493
1493
  let header = sign_stripe_header(secret, now, &payload);
1494
1494
 
1495
- let response = webhook_route(&payload, &header, &payments::test_platform_with_secret(secret), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1495
+ let response = webhook_route(&payload, &header, &payments::test_platform_with_secret(secret), &client, &wasm_path, &config, &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1496
1496
  assert_eq!(response["statusCode"], 200, "{response:?}");
1497
1497
 
1498
1498
  let read = dispatch::read(&client, &wasm_path).await.unwrap();
@@ -1511,7 +1511,7 @@ mod tests {
1511
1511
  let now = now_secs();
1512
1512
  let header = sign_stripe_header(secret, now, &payload);
1513
1513
 
1514
- let response = webhook_route(&payload, &header, &payments::test_platform_with_secret(secret), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::ir::fixture_payments()).await;
1514
+ let response = webhook_route(&payload, &header, &payments::test_platform_with_secret(secret), &client, &checkout_wasm_path(), &checkout_config(1), &lambda_client::NeverInvoker, &crate::commerce_ir::fixture_payments()).await;
1515
1515
  assert_eq!(response["statusCode"], 200);
1516
1516
  }
1517
1517
  }