import type { BackendInstanceId, BorrowedBytes, Capacity, Deadline, LeaseId, MonotonicTimestamp, OwnedBytes, PeerId, ScanSessionId, ScanShareToken, Uuid } from './primitives.js'; import type { PeerReference } from './peer-reference.js'; import type { ScanPlan } from './scan-planning.js'; import type { NormalizedScanQuery } from './scan-query.js'; /** How the backend obtained this observation, independent of individual field provenance. */ export type ObservationSource = 'platform-raw' | 'platform-derived' | 'core-merged'; export type FieldProvenance = 'observed' | 'derived' | 'synthesized' | 'not-provided'; export interface PresentField { readonly state: 'present'; readonly value: Value; readonly provenance: Exclude; } export interface AbsentField { readonly state: 'absent' | 'unavailable'; readonly reason: string; readonly provenance: FieldProvenance; } export type AdvertisementField = PresentField | AbsentField; /** Addresses are optional because several platforms expose only opaque device identities. */ export interface DeviceAddress { readonly value: string; readonly type: 'public' | 'random' | 'opaque'; } /** * Backend-scoped observation identity. It deliberately does not claim that a privacy-rotating * address or host-local ID identifies a physical device across backend lifetimes. */ export interface DeviceIdentity { readonly id: PeerId; readonly backendInstanceId: BackendInstanceId; readonly scope: 'session' | 'application' | 'backend'; readonly stableAcrossRestarts: boolean | null; readonly address: DeviceAddress | null; } /** Creates an immutable backend-scoped identity without making a global-physical-ID claim. */ export declare function deviceIdentity(id: PeerId, backendInstanceId: BackendInstanceId, address: DeviceAddress | null): DeviceIdentity; /** Monotonic source time and its clock provenance; receipt time remains separate on the observation. */ export interface SourceTimestamp { readonly monotonicMs: MonotonicTimestamp; readonly origin: 'platform' | 'backend'; } export interface ServiceDataEntry { readonly serviceUuid: Uuid; readonly value: OwnedBytes; } export interface ManufacturerData { readonly companyIdentifier: number; readonly value: OwnedBytes; } export interface AdvertisementObservation { readonly device: DeviceIdentity; /** Present only when the instantiated backend can issue a truthful scoped reference. */ readonly peerReference?: PeerReference; readonly provenance: ObservationSource; readonly sourceTimestamp: AdvertisementField; readonly receivedAtMonotonicMs: MonotonicTimestamp; readonly ingressOrdinal: number; readonly scanSessionId: ScanSessionId; readonly localName: AdvertisementField; readonly rssi: AdvertisementField; readonly txPower: AdvertisementField; readonly connectable: AdvertisementField; readonly appearance: AdvertisementField; readonly serviceUuids: AdvertisementField; readonly solicitedServiceUuids: AdvertisementField; readonly overflowServiceUuids: AdvertisementField; readonly serviceData: AdvertisementField; readonly manufacturerData: AdvertisementField; readonly rawRecord: AdvertisementField; readonly scanResponseRecord: AdvertisementField; } export interface ManufacturerDataFilter { readonly companyIdentifier: number; /** Null matches every payload for the company; a present prefix is matched byte-for-byte. */ readonly dataPrefix: Readonly | null; } export interface ScanFilter { readonly serviceUuids: readonly Uuid[]; readonly manufacturerData: readonly ManufacturerDataFilter[]; readonly localNamePrefix: string | null; readonly deviceAddresses?: readonly string[]; } export interface OwnerScanSharing { readonly mode: 'owner'; readonly allowSharing: boolean; } export interface JoinScanSharing { readonly mode: 'join'; readonly sharedLeaseId: LeaseId; readonly token: ScanShareToken; } export type ScanSharing = OwnerScanSharing | JoinScanSharing; export interface ScanOptions { readonly query?: NormalizedScanQuery; readonly plan?: ScanPlan; readonly filter: ScanFilter; readonly duplicatePolicy: 'all' | 'first' | 'merged'; readonly timestampPolicy: 'receipt-monotonic' | 'source-then-receipt'; readonly delivery: { readonly itemCapacity: Capacity; readonly byteCapacity: Capacity; readonly reservedControlCapacity: Capacity; readonly overflowPolicy: import('./streams.js').OverflowPolicy; }; readonly deadline: Deadline | null; readonly signal: AbortSignal | null; readonly sharing: ScanSharing; readonly platform?: { readonly kind: 'android' | 'corebluetooth' | 'winrt' | 'web' | 'electron' | 'tauri'; readonly mode?: 'low-power' | 'balanced' | 'low-latency' | 'opportunistic'; readonly callbackType?: 'all-matches' | 'first-match' | 'match-lost'; readonly reportDelayMs?: number; readonly legacy?: boolean; readonly phy?: 'all-supported' | '1m' | 'coded'; }; } export type OwnerScanOptions = Omit, 'sharing'> & { readonly sharing: OwnerScanSharing; }; export interface AdvertisementInput { readonly bytes: BorrowedBytes; } /** Rejects malformed manufacturer criteria before radio work begins. */ export declare function assertScanFilter(filter: ScanFilter, operation: string): void; /** One canonical software predicate used whenever a platform cannot install all filters natively. */ export declare function advertisementMatchesFilter(filter: ScanFilter, observation: AdvertisementObservation): boolean; //# sourceMappingURL=advertisement.d.ts.map