How it works

One age check. Three answers. Zero patron profiles.

Verification happens on the reader. Identity data stays in the local exchange. The only patron-derived value the platform receives is pass, fail, or unable_to_verify. It stores aggregate counts—not a record of the person.

01 · The complete answer set

The decision is deliberately small.

The local check resolves to one of three outcomes. No name, birth date, portrait, document number, or persistent patron identifier accompanies it.

pass

The mobile credential proves the requested age threshold.

fail

The credential answers that the requested age threshold is not met.

unable_to_verify

The reader cannot complete a trustworthy check, so staff use the normal fallback.

02 · Step by step

Five steps, one hard boundary.

Every step has one job: answer the age question without turning identity into data.

  1. Start the check locally

    A patron presents a mobile ID to the reader. Verification runs on-device, and the identity data involved in that exchange remains there.

    Local side The identity exchange and age check stay between the mobile ID and the reader.

  2. Resolve one closed answer

    The reader turns the local check into pass, fail, or unable_to_verify. There is no fourth outcome and no identity field attached to the answer.

    Patron-derived data One outcome. Nothing that identifies the patron.

  3. Cross the device boundary

    The outcome crosses into the platform. The identity data does not. The boundary is placed before platform ingestion, not after identity has been collected.

    What crosses The answer and the operational context required to process it—not identity.

  4. Keep operation separate from person

    Reader, venue, and processing context describe the configured system. They are operational metadata, not attributes from the patron's mobile ID. The outcome remains the only patron-derived answer.

    Operational context It identifies where the system ran—not who stood in front of it.

  5. Increment counts, not histories

    The platform stores aggregate outcome counters. It has no patron entity and no persistent patron profile. Day-level buckets stay suppressed below k=3 before a report renders.

    Persistent storage Aggregate counts only—never a patron record or per-patron timeline.

03 · The mechanism

The boundary is visible by design.

Identity remains in the local exchange on the left. One outcome crosses the device boundary. The platform side holds aggregate counters, not a patron profile.

Verification boundary

Explanatory model · no live patron data

04 · Boundary payload

Patron answer and operational context stay distinct.

The input shape is narrow. Only result comes from the age question; the remaining permitted fields describe the configured operation, never the patron.

Device → platform · allowlisted shape No identity fields
result pass · fail · unable_to_verify The only patron-derived answer in the payload.
device_id Operational reader identifier. Identifies configured equipment, never a patron.
location_id Operational venue identifier. Identifies the business location, never a patron.
occurred_at Operational processing time. Used to increment counters, not retain a patron visit.
failure_reason? Optional coarse operational category from a closed enum. Never a free-text field.
org_context_id? Optional operational organization context. Routes the operation; it does not identify a patron.
identity fields Not permitted across the boundary. No name, birth date, portrait, or document number.

Aggregate tier

Running outcome totals

Cumulative counts are grouped by location and outcome. There is no patron key or per-person dimension to turn those counts into a profile.

Protected breakdown

Day buckets, suppressed below k=3

Day-level location-and-outcome buckets remain withheld before reports render until the bucket reaches three.

05 · Straight answers

Questions about the boundary.

Does patron identity ever reach the platform?

No. Verification happens on-device, and identity data remains in that local exchange. The three-value outcome is the only patron-derived value that crosses; separate operational context identifies the configured system, never the patron.

Is operational metadata a patron record?

No. Reader, location, organization, and processing context describe the system running the check. They are not attributes taken from the patron. The outcome is the only patron-derived answer, and persistent storage keeps aggregate counters rather than an individual verification history.

Can Laurel Secure build a persistent patron profile?

No. The platform has no patron entity, patron identifier, or persistent patron profile. It stores outcome counts in aggregate instead of creating a record for each person.

What does k=3 suppression protect?

A very small day-level bucket could reveal too much about one moment even without a name. Laurel Secure withholds each location, day, and outcome bucket below three before it reaches a rendered report.

Is unable to verify the same as fail?

No. fail and unable_to_verify are separate outcomes. If the local check cannot return pass or fail, unable to verify keeps that uncertainty explicit without sending identity to the platform.

Evaluate the boundary with your team.

Start with the age-checking moment, inspect what crosses, and assess aggregate-only reporting in your own setting.