Skip to main content
Wildo.ai Coming soon

Authorization and isolation

Refuse access without exposing private records

A refusal should not reveal whether another customer’s record exists. Wildo separates the decision visible to the caller from the detail needed to investigate the refusal.

Two unknown targets lead to the same unavailable response, with an audit record kept separately.

Refuse access without exposing private records

A refusal should not reveal whether another customer’s record exists. Wildo separates the decision visible to the caller from the detail needed to investigate the refusal.

The authorization trail preserves a signal for repeated attempts while keeping outward responses from becoming a private-record directory.

Example — An account member guesses a record ID

A record outside the person’s accessible scope does not become discoverable through a different “you cannot access this existing record” response. The internal refusal still has a reason for investigation.

For engineers

Role checks that do not depend on the row can refuse before resolving it. A missing or scope-invisible addressed record uses the same outward not-found treatment. Internal storage faults remain faults rather than being rewritten as evidence that a record is absent.

CaseMeaning to preserve
Missing operation roleThe caller cannot use this action
Missing or inaccessible addressed recordNo accessible record can be returned
Repository or infrastructure failureThe operation failed; absence was not established

Keep a useful refusal trail

authorization-denial-audit.backend.utils.ts classifies authorizer-origin not-found outcomes as authorization refusals while excluding unrelated application 404s. The audit policy emits the first refusal and escalating occurrence counts, rather than writing an attacker-controlled number of rows.

The resource-operation authorization path uses this classifier to distinguish a concealed subject from an unrelated application failure. Exact excerpt from authorization-denial-audit.backend.utils.ts:

export function classifyAuthorizationDenial(
  error: unknown,
  phaseDefaultReason: ResourceOperationDenialReason,
): ResourceOperationDenialReason | undefined {
  if (!isWildoBackendError(error)) return undefined;

  if (error.type === ErrorType.AUTHORIZATION) {
    return error.customMessageReference === ErrorCustomMessageReference.AUTHORIZATIONS_MISSING_INITIATOR
      ? ResourceOperationDenialReason.MISSING_INITIATOR
      : phaseDefaultReason;
  }

  if (
    error.type === ErrorType.NOT_FOUND &&
    error.customMessageReference === ErrorCustomMessageReference.AUTHORIZATIONS_VALIDATION_FAILED
  ) {
    return ResourceOperationDenialReason.SUBJECT_NOT_RESOLVABLE;
  }

  return undefined;
}

The second branch recognizes only a not-found outcome marked by the authorizer. Other failures return undefined here; they keep their own error handling rather than entering the access-refusal series.

The counter is associated with the available user identity, resource, operation, variant and reason; calls without a user identity share the fallback bucket. Walking different target IDs therefore does not create an independent audit bucket for every guessed record.

Do not confuse observation with prevention

The normal authorization decision refuses the request. The audit volume policy does not rate-limit or lock the caller, and it does not normalize response timing. Security monitoring can act on the recorded pattern; application access rules remain the preventive control.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.