Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions apps/api-rust/tests/acquisition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,3 +728,126 @@ async fn postgres_registration_respects_visit_time_boundaries() {
fixture.cleanup().await;
}
}

#[tokio::test]
#[ignore = "requires isolated PostgreSQL via LMM_TEST_DATABASE_URL"]
async fn postgres_visit_consent_and_owner_boundaries_are_atomic() {
let fixture = PgFixture::new().await;
let visitor = "f".repeat(64);

let missing_consent = fixture
.store
.observe(
&visitor,
7,
&input(json!({
"consent":true,
"consent_version":2,
"nonce":"88888888888888888888888888888888",
"landing":"/guide",
"source":"documentation"
})),
&["api.lmm.best"],
)
.await;
assert!(matches!(missing_consent, Err(Error::Invalid(_))));
let empty: (i64, i64) = sqlx::query_as(
"SELECT (SELECT COUNT(*) FROM acquisition_visitors),\
(SELECT COUNT(*) FROM acquisition_visits)",
)
.fetch_one(&fixture.pg)
.await
.unwrap();
assert_eq!(
empty,
(0, 0),
"rejected consent must not persist partial rows"
);

let legacy = fixture
.store
.observe(
&visitor,
7,
&input(json!({
"consent":true,
"consent_version":1,
"nonce":"99999999999999999999999999999999",
"landing":"/guide",
"source":"documentation"
})),
&["api.lmm.best"],
)
.await
.unwrap();
assert_eq!(legacy.consent_version, 1);

sqlx::query("INSERT INTO users VALUES(8,1700000000,NULL)")
.execute(&fixture.pg)
.await
.unwrap();
fixture.store.grant(8).await.unwrap();
let foreign_owner = fixture
.store
.observe(
&visitor,
8,
&input(json!({
"consent":true,
"consent_version":2,
"nonce":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"landing":"/pricing",
"source":"community"
})),
&["api.lmm.best"],
)
.await;
assert!(matches!(foreign_owner, Err(Error::Invalid(_))));

let state: (i64, i64, i64) = sqlx::query_as(
"SELECT (SELECT user_id FROM acquisition_visitors WHERE id=$1),\
(SELECT COUNT(*) FROM acquisition_visits WHERE visitor_id=$1),\
(SELECT COUNT(*) FROM acquisition_visits \
WHERE visitor_id=$1 AND nonce='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')",
)
.bind(&visitor)
.fetch_one(&fixture.pg)
.await
.unwrap();
assert_eq!(
state,
(7, 1, 0),
"owner conflict must roll back every write"
);

fixture.store.grant(7).await.unwrap();
let upgraded = fixture
.store
.observe(
&visitor,
7,
&input(json!({
"consent":true,
"consent_version":2,
"nonce":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"landing":"/pricing",
"source":"community"
})),
&["api.lmm.best"],
)
.await
.unwrap();
assert_eq!(upgraded.consent_version, 2);
let final_state: (i64, i64, bool, i64) = sqlx::query_as(
"SELECT (SELECT user_id FROM acquisition_visitors WHERE id=$1),\
(SELECT COUNT(*) FROM acquisition_visits WHERE visitor_id=$1),\
(SELECT allowed FROM acquisition_consents WHERE user_id=7),\
(SELECT version FROM acquisition_consents WHERE user_id=7)",
)
.bind(&visitor)
.fetch_one(&fixture.pg)
.await
.unwrap();
assert_eq!(final_state, (7, 2, true, 2));
fixture.cleanup().await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ declare -A requirements=(
[scripts.rs]='repository_options_commit_refresh_runtime_invalidate_cache_and_redact_audit|LMM_TEST_DATABASE_URL|LMM_AUTH_TEST_VALKEY_URL'
[ai_directory.rs]='postgres_cache_and_audit_failures_do_not_reverse_committed_wallet_changes,postgres_create_replay_quote_changes_and_concurrency_charge_once,postgres_hide_refunds_once_and_wallet_failure_rolls_back_visibility,postgres_public_private_pagination_expiry_and_http_contract|LMM_TEST_DATABASE_URL|LMM_AUTH_TEST_VALKEY_URL'
[token_queries.rs]='configured_token_prices_match_current_go_reference_live_maps_and_limits,persisted_usage_is_exact_token_scoped_utc_and_never_changes_credentials,quota_query_auth_checks_exact_key_expiry_owner_oauth_and_ip_without_status_writes,quota_query_limiter_is_shared_per_owner_across_keys_and_instances,token_pricing_checks_permissions_before_query_validation_and_never_mutates_key,token_pricing_uses_shared_credited_trust_facts_and_excludes_internal_credits|LMM_TEST_DATABASE_URL|LMM_AUTH_TEST_VALKEY_URL'
[acquisition.rs]='postgres_consent_visit_report_and_withdrawal_round_trip,postgres_link_policy_and_lookback_contracts_are_durable,postgres_registration_cannot_override_explicit_consent_denial,postgres_registration_keeps_first_touch_and_selects_last_external_visit,postgres_registration_respects_visit_time_boundaries|LMM_TEST_DATABASE_URL|'
[acquisition.rs]='postgres_consent_visit_report_and_withdrawal_round_trip,postgres_link_policy_and_lookback_contracts_are_durable,postgres_registration_cannot_override_explicit_consent_denial,postgres_registration_keeps_first_touch_and_selects_last_external_visit,postgres_registration_respects_visit_time_boundaries,postgres_visit_consent_and_owner_boundaries_are_atomic|LMM_TEST_DATABASE_URL|'
)

total_ignored=0
Expand Down
4 changes: 2 additions & 2 deletions apps/api-rust/tests/scripts/run-real-integration-gates.sh
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ run_token_queries() (

run_acquisition() {
require_loopback_url LMM_TEST_DATABASE_URL
require_api_ignored_test_count acquisition 5
run_counted_api_integration_tests acquisition 5
require_api_ignored_test_count acquisition 6
run_counted_api_integration_tests acquisition 6
}

run_shared_trust() {
Expand Down
Loading