Skip to content

Add the cargo acceptance arm for the registrar surface #781

Description

@sehkone

Add the cargo acceptance arm for the registrar surface

Context

The registrar has fast library tests and socket tests already, but they do not yet prove two required assembled behaviors. src/registrar/verbs/tests.rs::a_pre_decision_flood_is_limited_without_writing_a_record drives real verb requests, but uses a burst of 2 and a recording sink; it does not use the coalescing sink, the shipped burst of 32, floods of 40 and 256, or compare durable record totals. src/registrar/verbs/coalescing/tests.rs::windows_coalesce_by_key_and_forward_every_event_to_the_counter proves coalescing at its unit seam, but does not drive requests through the verb layer.

Likewise, src/registrar/endpoint/tests.rs::responses_relay_the_last_capacity_snapshot_without_scanning_the_store relays a LowWater snapshot through a handler call, and src/registrar/endpoint/production/tests.rs::a_mint_response_relays_the_last_snapshot_without_scanning_the_store proves snapshot relay. Neither drives a mint request through the activated Unix socket with an Exhausted snapshot, nor proves the LowWater and Unknown complements. The only Exhausted assertion is src/registrar/endpoint/protocol.rs::an_exhausted_audit_refusal_preserves_the_health_snapshot, which tests codec encoding in isolation.

src/registrar/tests.rs::the_derivation_is_not_injective proves that web on h1-aimer and aimer-web on h1, each at instance 1, derive h1-aimer-web-001. The corresponding full durable-binding scenario in src/registrar/verbs/tests.rs::a_second_host_is_refused_before_the_spec_comparison_across_instances is ignored because it requires live OpenBao. This arm keeps its added coverage library-side and runnable by ordinary cargo test, without Docker or root.

Scope

Add the missing cargo-tier tests beside the library registrar verbs and endpoint. Document in the relevant test-module documentation that every socket the arm binds or dials is either a Unix socket under tempfile::tempdir() or a loopback wiremock::MockServer started and stopped by the test process. Do not add a binary-crate test: verbs and endpoint are pub(crate) library modules, so their tests belong in their existing #[cfg(test)] library modules.

Add a verb-layer refusal-flood test using CoalescingLimitedInvocationSink, its CountingLimitedInvocationSink, and the default VerbRateLimiterSettings. Pause Tokio time, use one caller and one mint verb, and choose a coalescing window longer than the flood. Drive identical invalid-label mint requests through RegistrarVerbs, then flush the sink. Run independent floods of 40 and 256 requests.

Add an activated-Unix-socket test over ProductionHandler::with_health and a shared Arc<StdMutex<RegistrarHealth>>. Drive the same valid mint request with the snapshot set to Exhausted, LowWater, and Unknown. This test uses the existing production constructor and health snapshot only; it does not use or add an audit-capacity probe implementation.

Add a fast synthetic collision case using RegistrarConfigFixture::new().with_multiplicity("web", Multiplicity::ManyPerHost).with_multiplicity("aimer-web", Multiplicity::ManyPerHost). The added components use the fixture's default ReloadSpec::none() and no certificate group, so both colliding mint requests must supply that same empty requested spec. Exercise the two derived identities through the verb-layer collision path with the existing canned Wiremock binding responses; do not copy or hand-write a registrar config.

Acceptance criteria

  • The refusal-flood test pauses Tokio time and uses the shipped pre-decision refusal configuration: a full bucket with burst 32 and 1,000 ms refill interval, one caller, one mint verb, and a coalescing window that remains open for the flood.
  • For each of N = 40 and N = 256 identical requests whose service name is not a DNS label, the real verb path returns the normal pre-decision refusal, writes exactly 2 * 32 + 1 = 65 audit records after the coalescing sink is flushed, and the totals are identical between the two floods.
  • In each flood, the 64 admitted-request records are 32 intent/refusal pairs and the sole limited record is for the pre-decision-refusal bucket with count == N - 32; CountingLimitedInvocationSink::count(LimiterBucket::PredecisionRefusal) == N - 32 and CountingLimitedInvocationSink::count(LimiterBucket::Admission) == 0. The test thereby proves bounded durable records without losing the suppressed-invocation evidence.
  • The flood test drives RegistrarVerbs rather than calling the limited-invocation sink directly, and it does not duplicate the coalescing module's unit tests.
  • With audit_capacity.state == Exhausted, a valid mint request driven through the activated tempfile Unix socket returns a permanent RegistrarUnavailable { reason: AuditUnwritable } refusal carrying the request id and no registration_id. It writes no audit intent record and makes no Wiremock request, proving no role, policy, KV path, or binding is created.
  • With the same socket request and snapshot state LowWater or Unknown, the capacity gate does not return AuditUnwritable and the request proceeds into the verb layer; the test observes the normal verb-path outcome and its audit activity.
  • The collision fixture loads through RegistrarConfig, both web/h1-aimer/1 and aimer-web/h1/1 use ReloadSpec::none() with no certificate group, and both derive h1-aimer-web-001. After the first mint claims that identity, the second mint is refused as VerbError::RegistrationIdCollision { stored_host, .. } with stored_host == "h1-aimer", on ProducingArm::Binding; its audit outcome has reason registration_id_collision and registration id h1-aimer-web-001.
  • All new cases are unignored library tests run by ordinary cargo test; they need neither Docker nor root, and their module documentation makes the test-owned Unix-socket and in-process-loopback boundary explicit.

Constraints

Do not change production registrar behavior, add visibility, introduce a test-only production hook, copy the fixture builder, hand-write rendered registrar configuration, or introduce a stateful OpenBao fake. Do not use CapacityProbe, HostCapacityProbe, or WalkOps: the capacity case sets the daemon-owned health snapshot's AuditCapacityHealth::state. Do not add actual network isolation, fixed ports, environment-derived addresses, external services, or a Docker dependency; the requirement is that the cases have no dependency outside the test process.

Do not move credential-boundary, root-owned-socket, certificate-renewal, or no-AppRole assertions into this cargo arm.

Out of scope

  • Docker-backed or live-OpenBao durable-binding tests.
  • Audit-capacity probe arithmetic, filesystem walking, low-water hysteresis, and daemon maintenance-tick tests.
  • Production code changes, CI wiring, and binary-crate tests.

Test plan

  • Run the new verb and endpoint library tests with cargo test --lib.
  • Run plain cargo test with Docker unavailable. Confirm the added cases remain green and inspect them to confirm every bound or dialed socket is a tempfile Unix socket or an in-process loopback Wiremock stub.
  • Run cargo fmt -- --check --config group_imports=StdExternalCrate and cargo clippy --all-targets -- -D warnings.
  • Run scripts/preflight/run-all.sh. If passwordless sudo is unavailable, run scripts/preflight/ci/e2e-matrix.sh as far as it can proceed and leave the affected Docker matrix arm to CI without weakening or skipping it.

Dependencies

Part of #784. The existing RegistrarConfigFixture, coalescing sink, production health-snapshot constructor, and activated-endpoint harness are sufficient; no implementation dependency is required.

Pointers

  • src/registrar/verbs/tests.rs::a_pre_decision_flood_is_limited_without_writing_a_record
  • src/registrar/verbs/coalescing/tests.rs::windows_coalesce_by_key_and_forward_every_event_to_the_counter
  • src/registrar/verbs/limiter.rs::DEFAULT_RATE_LIMIT_PREDECISION_REFUSAL_BURST
  • src/registrar/endpoint/tests.rs::production_handler_with_limiter
  • src/registrar/endpoint/production.rs::ProductionHandler::with_health
  • src/registrar/endpoint/protocol.rs::encode_audit_capacity_exhausted
  • src/registrar/fixture.rs::RegistrarConfigFixture::with_multiplicity
  • src/registrar/tests.rs::the_derivation_is_not_injective

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions