Task
dig_sex::admission -- AdmissionMeter::admit / release, AdmissionLimits, WorkKind, Refusal -- is implemented, tested, and gates nothing. The node does the work first and has no admission step at all.
Why it matters
Admit before you work. The value of an admission meter is that it refuses before spending anything. Calling it after the expensive part is decoration.
Meter by the AUTHENTICATED identity, never a placeholder. AuthenticatedPeer is a newtype for exactly this reason. Passing a constant, a connection id, or an unauthenticated claim collapses every requestor into one shared bucket, which turns a per-peer limit into a global one -- so a single peer can exhaust the allowance for everybody. That failure looks like working DoS protection right up until it matters.
Context
- The inbound request handlers in
crates/dig-node-core/src/lib.rs. admit goes before any read, fetch or decode.
release must be called on every exit path from admitted work, including error paths. A release skipped on failure leaks allowance until the node refuses everything.
- dig-sex
SPEC.md section 8.5.
Scope
Thinnest path: gate the request kinds that actually cost something. Do not invent limit categories beyond what WorkKind already declares.
Evidence
A test that fails without the fix: exceed the per-peer limit and assert a Refusal before the work is performed, then assert a second peer is unaffected. That second half is what catches the shared-bucket mistake.
Parent
Orchestrator epic: https://github.com/DIG-Network/dig_ecosystem/issues/3138
Task
dig_sex::admission--AdmissionMeter::admit/release,AdmissionLimits,WorkKind,Refusal-- is implemented, tested, and gates nothing. The node does the work first and has no admission step at all.Why it matters
Admit before you work. The value of an admission meter is that it refuses before spending anything. Calling it after the expensive part is decoration.
Meter by the AUTHENTICATED identity, never a placeholder.
AuthenticatedPeeris a newtype for exactly this reason. Passing a constant, a connection id, or an unauthenticated claim collapses every requestor into one shared bucket, which turns a per-peer limit into a global one -- so a single peer can exhaust the allowance for everybody. That failure looks like working DoS protection right up until it matters.Context
crates/dig-node-core/src/lib.rs.admitgoes before any read, fetch or decode.releasemust be called on every exit path from admitted work, including error paths. Areleaseskipped on failure leaks allowance until the node refuses everything.SPEC.mdsection 8.5.Scope
Thinnest path: gate the request kinds that actually cost something. Do not invent limit categories beyond what
WorkKindalready declares.Evidence
A test that fails without the fix: exceed the per-peer limit and assert a
Refusalbefore the work is performed, then assert a second peer is unaffected. That second half is what catches the shared-bucket mistake.Parent
Orchestrator epic: https://github.com/DIG-Network/dig_ecosystem/issues/3138