package session import "context" // Platform is the trusted execution context recorded on a session: the wrapper // Kind the session was established through and the device Subtype. An empty Kind // marks an untrusted session — one minted before platform capture, or one the // gateway could not attribute — which the payments compliance gate treats as // view-only. // // Kind is always trustworthy: it is derived server-side from the validated // establish path, never from a client-supplied field. Subtype is trustworthy only // for VK (vk_platform rides inside the signed launch params); for telegram and // direct it is client-reported and best-effort, so the gate must never rely on it. type Platform struct { Kind string Subtype string } // Platform kinds recorded in platform_kind. const ( PlatformKindVK = "vk" PlatformKindTelegram = "telegram" PlatformKindDirect = "direct" ) // Platform subtypes recorded in platform_subtype. const ( SubtypeIOS = "ios" SubtypeAndroid = "android" SubtypeWeb = "web" ) // Trusted reports whether the session was attributed to a platform (a non-empty // Kind). The zero Platform is untrusted. func (p Platform) Trusted() bool { return p.Kind != "" } // NormalizeSubtype coerces subtype to one of the known device families, defaulting // an empty or unrecognised value to web. A newly established session always carries // at least a web subtype, so a trusted session is never left without one. func NormalizeSubtype(subtype string) string { switch subtype { case SubtypeIOS, SubtypeAndroid, SubtypeWeb: return subtype default: return SubtypeWeb } } // platformCtxKey types the request-context slot the trusted platform rides in. type platformCtxKey struct{} // WithPlatform returns a copy of ctx carrying platform. The backend middleware // calls it after parsing the gateway-injected X-Platform header, so downstream // handlers and the link/merge session mint read the caller's platform from ctx. func WithPlatform(ctx context.Context, platform Platform) context.Context { return context.WithValue(ctx, platformCtxKey{}, platform) } // PlatformFromContext returns the platform stored by WithPlatform and whether one // was present. A missing value yields the zero (untrusted) Platform. func PlatformFromContext(ctx context.Context) (Platform, bool) { p, ok := ctx.Value(platformCtxKey{}).(Platform) return p, ok }