Build abuse controls for a permit portal used from home, shared municipal offices, and an embedded review station. Public recovery requests return one generic response shape whether an account exists or not; delivery occurs asynchronously so the request path does not expose a simple timing split. Identity, source, and provider-spend budgets prevent a distributed client from making unlimited mail requests. A reviewer who is limited gets a safe help route, and recovery tokens remain short-lived and single-use. Search requests carry bounded page size, filter count, execution time, and tenant concurrency before database work starts. A large export becomes a job with a status path instead of an unbounded synchronous request. A challenge may be offered for suspicious expensive actions, but it does not override record permission or the tenant budget. The UI includes an accessible alternate process for people who cannot complete a visual challenge. The rules store only bounded decision categories in routine telemetry. A new export rule rolls out to a small cohort with measured legitimate task completion, appeals, and resource use. If 83 reviewers behind one address are blocked, the team can disable that rule version while keeping base authorization and work limits active. The project has an operator record for each rule: owner, version, exposure, thresholds, stop action, and short raw-signal retention. An automatic block count is never presented as proof of success by itself.
Project: public permit endpoint abuse controls
Build contract
- Keep known and unknown recovery identities publicly indistinguishable.
- Bound both request rate and actual compute, bytes, and provider spend.
- Make challenges action-scoped with an accessible alternative.
- Stage and roll back a mistaken rule without dropping base protection.
Implementation checkpoint
function admitPermitExport(request) {
if (!request.recordAuthorized) return 'deny';
if (request.tenantCostRemaining < request.estimatedCost) return 'defer';
if (request.challengeRequired && !request.challengePassed) return 'challenge';
return 'admit';
}
console.log(admitPermitExport({ recordAuthorized: true, tenantCostRemaining: 19, estimatedCost: 31, challengeRequired: false, challengePassed: false }));
// Output: deferCost and boundaries
A request counter is O(1), but reliable enforcement across distributed servers has storage and consistency costs. Search admission takes O(filter count) after a hard filter bound; the expensive query must still have a timeout and result-byte limit. Third-party sends incur direct charges. Challenges add abandonment and sometimes vendor script weight. Telemetry needs bounded categories rather than raw case IDs or device histories. Measure legitimate completion, false-positive appeals, provider charges, database CPU, queue age, and ordinary case-read latency under 83 parallel expensive requests.
Failure drill
Compare public recovery responses for a known and unknown address across body, status, and repeated timings. Send 83 requests from one network against distinct accounts, then distribute requests to one account from multiple networks; limits should cover both. Request huge search pages and nested filters, then verify denial before database work. Trigger a challenge with a screen reader, complete its alternative, and still require the tenant export budget. Block the challenge vendor script and preserve the help path. Roll out a new rule that catches a shared-office network, watch legitimate completion fall, and disable only that rule. Review logs for private tokens, raw search text, and signal retention expiry.
Acceptance checks
- Recovery behavior does not reveal account existence.
- Work budgets bind parallel and expensive operations.
- Challenge success does not waive authorization or cost limits.
- False positives trigger a narrow, auditable rollback.
Common Mistakes
- Relying only on an IP counter.
- Adding a puzzle to every task without an alternate route.
- Calling a rule successful because blocks increased.
Related lessons
Account Recovery Enumeration and Throttle Policy; Expensive Request Work Budgets and Load Shedding; Human Challenges, Accessible Alternatives, and Signal Retention; Abuse Decision Telemetry and False-Positive Rollback.
