Phase 5 Customer Discovery

Status

Phase 5 is active under Issue #23. This checkpoint is synthetic and must not be interpreted as a production map, location, publication or customer-search deployment.

Purpose

Phase 5 turns Phase 4 scoped claim cards into a customer-facing discovery contract without exposing original evidence, reviewer information or precise private provider locations.

The phase implements:

  • customer onboarding and location-permission education;
  • manual and one-time-location search models;
  • policy-controlled provider/category publication;
  • public-safe PostGIS search;
  • list and synthetic map presentation;
  • public provider/trust profiles;
  • saves and share-safe metadata;
  • low-bandwidth and image-free presentation;
  • deterministic empty, sparse and no-location states.

Publication model

A publication is a provider/category projection, not a provider-owned flag.

discovery.refresh_publication() is the only database function permitted to create or refresh a publication. A trigger rejects direct inserts, updates and deletes unless the policy function has established the transaction-local publication context.

Publication requires:

  1. an active selected provider category and pinned requirement version;
  2. provider state ready_for_verification;
  3. a public-safe location record and service area;
  4. a consented public premises point for fixed and hybrid providers;
  5. one current active scoped claim for every mandatory requirement;
  6. an explicit publication policy version.

Public search re-evaluates provider state and mandatory claim freshness on every query. A stale publication snapshot therefore cannot keep a suspended provider or expired mandatory claim visible.

Payment, profile completion, administrator row edits and client input are not publication inputs.

Location types

discovery.provider_locations stores distinct fields:

  • private_base: restricted operating-base evidence; never serialized publicly;
  • public_premises: optional consented public point suitable for customer presentation;
  • service_area: non-private polygon used for mobile/hybrid compatibility;
  • public_locality: coarse human-readable public description;
  • source, confidence and confirmation timestamp.

The public projection contains only the consented public premises point and public service-area geometry.

Fixed premises

Distance may be calculated only from public_premises. Publication requires a consented public point.

Mobile

Search uses ST_Covers(service_area, origin). No public point or distance from the provider’s private base is returned.

Hybrid

Search may match either the public premises distance or the public service area. The private base remains excluded.

Customer location

Version 1 prohibits background location.

The Android model provides:

  • manual area/landmark entry as the default and permanent fallback;
  • a one-time current-area education path;
  • no continuous tracking;
  • no retained exact customer coordinate in the synthetic state;
  • no ranking penalty for manual selection.

Real permission requests, geocoding and map SDK traffic remain integration gates.

Search contract

Public endpoints:

GET /api/v1/public/categories
GET /api/v1/public/providers/search
GET /api/v1/public/providers/{publicProviderId}
GET /api/v1/public/providers/{publicProviderId}/claims
GET /api/v1/public/providers/{publicProviderId}/availability
GET /api/v1/public/providers/{publicProviderId}/share

Search supports:

  • category;
  • normalized text;
  • manual area;
  • optional one-time latitude/longitude origin;
  • public-premises radius;
  • operating model;
  • minimal availability state;
  • scoped claim key;
  • bounded limit and opaque cursor.

Ordering is deterministic:

  1. service-area compatibility;
  2. consented public-premises distance where applicable;
  3. public display name;
  4. public publication ID.

The cursor contains only a versioned offset encoded as opaque base64url. It does not contain a private provider ID, coordinate or evidence reference.

Explainability

Allowlisted result reasons are generated by the backend from safe data:

  • Current mandatory checks;
  • Serves your selected area;
  • Public premises within selected distance;
  • Currently marked available.

Android does not infer verification or ranking reasons.

Public DTO boundary

Public cards expose:

  • public provider ID;
  • category and public display name;
  • operating model;
  • public locality;
  • consented public premises or service-area geometry;
  • minimal availability;
  • approved public image variants;
  • current scoped claim cards and limitations;
  • allowlisted reasons;
  • public distance where lawful;
  • share-safe path.

They do not expose:

  • internal provider ID;
  • private base;
  • original evidence or storage key;
  • document or contact identifiers;
  • reviewer, assignment or decision notes;
  • exact customer location;
  • payment or subscription state.

Saves and sharing

Authenticated customers may save only an eligible public publication ID. Saved-provider reads dynamically exclude hidden, suspended or stale publications.

Share metadata contains public ID, public name, category, locality and a relative public path. It contains no private location or contact handoff.

Media and low bandwidth

Approved public media may provide separate low-bandwidth and standard URLs plus alt text. Images are optional.

Android supports:

  • data-saver preference;
  • standard preference with low-bandwidth fallback;
  • image-free mode;
  • complete text, location, claim and availability presentation without an image.

Real object storage/CDN integration remains deferred until the dedicated DIREKT infrastructure and secrets are available.

No-results behavior

Empty search returns an empty item list and safe suggestions to:

  • try a nearby area or landmark;
  • remove a filter or increase public-premises distance;
  • choose another active category.

The backend and Android never fabricate providers.

Operations visibility

The operations portal shows synthetic publication eligibility:

  • provider/category and operating model;
  • public locality and safe location readiness;
  • mandatory-claim freshness;
  • publication state.

It does not display private coordinates, evidence details or a direct database publication bypass.

Automated controls

The Phase 5 regression suite must prove:

  • direct publication writes fail;
  • incomplete mandatory claims cannot publish;
  • private coordinates and internal IDs are absent from public responses;
  • fixed, mobile and hybrid providers use the correct safe geospatial behavior;
  • manual area and one-time-origin searches both work;
  • multi-filter cursor pagination is deterministic;
  • suspended and stale-claim providers disappear dynamically;
  • claim limitations, image fallback and share metadata remain safe;
  • saves use only public IDs;
  • no-results recovery returns no fabricated provider.

External integration handoff

When approved integrations become available:

  • Google Maps/Places/Geocoding replace only the location adapter and Android map renderer;
  • Supabase/private storage remains behind the existing storage adapter;
  • Cloud Run and Vercel consume the existing API boundary;
  • Firebase may distribute and observe the Android build;
  • no external integration may bypass publication, claim freshness or privacy rules.