Product Spec¶
| Field | Value |
|---|---|
| Status | live working spec |
| Owner | PRODUCT OWNER / DIR |
| Applies to | Product behavior, user-facing flows, product policy assumptions, and release-scope choices for Partile. |
| Last updated | 2026-06-11 |
| Evidence | user-journeys.md; product-decisions.md; READINESS.md; readiness/*.md; implemented PRs in partile-infra, partile-mobile, partile-ops, and partile-dataroom. |
Purpose¶
This is the product owner's durable spec for what Partile is, how the product behaves, and what assumptions engineering should use when product input would otherwise become a blocker. It is intentionally current-state and working- assumption oriented, not marketing copy.
Operating Rule¶
Product decisions do not block engineering by default. When a product decision is needed, the director should:
- Propose a conservative MVP working assumption.
- Record it in
product-decisions.md. - Put the assumption in the relevant PR spec/notes.
- Keep the PR moving unless the operator explicitly asks to stop or the choice would cause major rework if wrong.
After every passed PR, update this product spec if the PR changes or clarifies user-facing behavior, product policy, release scope, safety behavior, consent behavior, messaging behavior, platform support, or event semantics.
Current Product Shape¶
Partile is a professional-networking-only airport product. It is not dating, not casual encounters, and not a generic airport chat room. A signed-in traveler enters the airport professional graph only by presenting a verified boarding pass. The boarding pass establishes airport X plus time window W; the matching pool is everyone whose verified window overlaps at the same airport. If two people do not share both place and time, Partile does not match them.
The current canonical discovery model is an open, relevance-ranked directory of everyone in the traveler's verified window, with starring/shortlist workflow. The backend in-window directory endpoint, internal-signal relevance ranking, and mobile local-only starring are merged. The connect model is request-to-connect with a note. The recipient reads the note before accepting or declining; backend and mobile request-with-note flows are merged, including incoming/outgoing lists and accept-to-conversation. AI-generated "why you two" rationale is implemented in the backend as a key-gated Claude integration with minimized prompt inputs and cached pair output. This supersedes the older dating-style approve/dismiss double-opt-in model as the product source of truth. PDL/ZoomInfo enrichment is deferred: the vendors remain planned and not contracted, and no broker data is processed yet. If later enabled, enrichment is a silent internal matching signal only; it is never displayed, redistributed, or presented as profile content. The AI scope for v1 is match rationale plus the optional AI profile interview using the real Claude API; both backend integrations are implemented key-gated, while the mobile interview UI remains upcoming. AI icebreakers and AI scheduling are out of scope.
Accepted requests open structured professional chat. The request note is the
opener, and message send now exists in both backend and mobile composer form.
The recipient-intent confirmation and propose-to-meet flow are still upcoming:
no built surface yet reveals gate/area or a neutral Heathrow meeting spot after
mutual accept-to-meet. Connections persist post-trip as durable professional
contacts; backend GET /connections is merged, while independent retention
duration remains pending C28. Discovery remains bound to the verified
airport/time window. Message events record metadata only, never message body. Heathrow
is the launch airport.
Implementation honesty: existing merged evidence proves LinkedIn auth, the
boarding-pass gate, camera scan/import, derived-only presence creation, safety
surfaces, consent primitives, backend message-send, the in-window backend
directory, backend relevance ranking, backend request-with-note/accept/decline,
backend profile/intent tags, backend cached AI rationale, backend advisory AI
profile interview, backend persistent connections list, and the mobile message,
directory/star, connect/request, safety, and profile-edit surfaces through mobile
PR-26. Infra PR-22 (2680a01) adds POST /conversations/{id}/messages with a
consent-gated metadata-only message.sent event. Infra PR-23 (75d8337) adds
GET /directory for the verified shared place/time pool with minimized cards.
Infra PR-24 (a6cf2af) adds directional connection requests with note, accept,
decline, conversation bridge, and connection event tiers. Infra PR-25
(0934291) adds GET/PUT /profile, the six-tag intent set, and headline plus
intent tags on counterpart cards. Infra PR-26 (e40f0fd) adds deterministic
internal-signal ranking without exposing scores. Infra PR-27 (e43b60c) adds
Claude Haiku 4.5 rationale generation, prompt minimization, and pair/hash
caching; absent ANTHROPIC_API_KEY, API cards carry null rationale. Infra
PR-28 (d2db03f) adds key-gated /profile/interview using Claude Sonnet 4.6
structured output; absent ANTHROPIC_API_KEY, it returns clean 503 and writes
no profile summary/events. Infra PR-29 (1fbcf6e) adds GET /connections.
Mobile PR-23 (ea3aaac) adds the message composer, mobile PR-24 (c441157)
adds directory browsing plus local-only stars, mobile PR-25 (12615d7) adds
request-with-note/incoming/outgoing/accept-to-conversation and restores
block/report on directory plus incoming-request cards, and mobile PR-26
(88cf083) adds profile and intent-tag capture. Broker enrichment, mobile AI
interview UI, persistent connection retention policy, and Heathrow meet-up reveal
details remain upcoming or deferred and are not marked implemented here.
Identity is LinkedIn OIDC. The app stores only the backend app session and minimal session state client-side; backend OAuth tokens are not persisted.
Current User-Facing Flows¶
- Sign in / session: LinkedIn auth handoff through the backend, then app session storage on mobile. Logout revokes the session and clears local state.
- Profile bootstrap: LinkedIn profile import starts the professional profile.
Backend PR-25 (
0934291) implementsGET/PUT /profilewith self-authored headline, summary, and the closed quick-intent tag set. Mobile PR-26 (88cf083) implements the profile-edit UI for headline, summary, and up to five intent tags. Backend PR-28 (d2db03f) implements the optional advisory AI interview endpoint, key-gated behindANTHROPIC_API_KEY; the mobile interview UI remains upcoming. PDL/ZoomInfo enrichment is deferred; no broker processing occurs yet. - Presence: a verified boarding pass creates presence; manual flight entry is
not a product path. Backend PR-21 enforces the product write contract
(
boarding_pass_barcode+document_verified), rejects manual/self-reported/ unverified product presence, rejects raw boarding-pass secrets, and stores only minimal normalized travel context. Mobile PR-15 implements the gate shell and removes manual presence creation. Mobile PR-16 implements camera barcode scan, on-device minimal BCBP decode, sanitized confirmation, and verified presence creation. Mobile PR-17 implements image/screenshot import from Photos/Files through the same local barcode decode and verified-presence path; PDFs and non-images are unsupported/fail closed. Mobile PR-18 physically verifies the scan/import/confirm/create/unlock flow on a real iPhone and fixes the scanner preview hard gate observed during QA. - Discovery: the target product flow is a relevance-ranked directory of
everyone in the traveler's verified airport/time window. Backend PR-23
(
75d8337) implements the in-window directory with minimized cards, symmetric block exclusion, verified place/time scoping, and rate limiting. Backend PR-26 (e40f0fd) implements deterministic ranking from internal profile signals only and does not expose raw scores. Mobile PR-24 (c441157) implements the directory screen and local-only stars/shortlist. Filters remain upcoming. Empty or thin windows are acceptable data state; Partile does not fabricate matches. - Profile card: the card shows LinkedIn-grade profile information plus the
implemented headline and intent tags. Backend PR-27 (
e43b60c) implements the symmetric cached AI match rationale, key-gated behindANTHROPIC_API_KEY. It does not show data-broker enrichment. - Connect request: a user sends a short note explaining why they want to
connect. Backend PR-24 (
a6cf2af) implements directional requests with note, accept, decline, conversation creation on accept, no-leak target checks, rate limiting, and note-free connection events. Mobile PR-25 (12615d7) implements request-with-note, incoming/outgoing request lists, accept-to-conversation, and decline/remove behavior. The recipient reads the note before accepting or declining; cached rationale can appear on request cards when available. Declines are silent to the sender and stale requests expire with the trip window. - Conversation and messages: accept opens a professional thread. The note is
the opener, the recipient confirms intent (Advice / Intro / Hiring / Pitch /
Just connect), and plain-text message send is implemented in backend PR-22
(
2680a01) for active conversations. Mobile PR-23 (ea3aaac) implements the message composer/send surface. Realtime delivery, typing indicators, read receipts, AI openers, and AI scheduling are deferred. - Propose to meet: not built. The target product assumption remains that either side can propose to meet and only mutual accept reveals the gate/area and a suggested neutral Heathrow in-terminal spot.
- Persistent connections: accepted connections persist after the trip as
durable professional contacts; only discovery remains window-bound. Backend
PR-29 (
1fbcf6e) implementsGET /connectionsfor accepted, non-blocked, self-scoped contacts and conversation links. Retention duration and erasure treatment are pending C28. - Safety: users can block, report, or report-and-block a counterpart from cards and conversations; mobile PR-25 restores/extends those actions to directory cards and incoming connection-request cards. Settings includes blocked-list management. Meeting suggestions are public, neutral, in-terminal spots only, and the propose-to-meet surface is not built yet.
- Rate limits: backend rate limits auth, presence writes, and match actions;
backend PR-22 adds message-send limiting, PR-23 adds directory limiting, and
PR-24 adds connection-request limiting; PR-28 adds the AI interview bucket.
Mobile preserves
429+Retry-Afteras a non-logout error. - Consent: backend consent primitives exist for
analytics,ml_training, andmarketing; mobile PR-13 adds Settings privacy choices plus a non-blocking first-run prompt. Final external notice copy is not built. - Platforms / launch scope: iOS is the primary dev-build path. Apple
Developer Program enrollment is complete; mobile PR-14 adds the iOS EAS
dev-build/auth-smoke checklist and confirms dev API preflight is green. On
2026-06-08 the physical iPhone EAS development build installed and real
LinkedIn
partile://auth/deep-link smoke passed after infra hotfixc91bd0faligned the LinkedIn OIDC issuer default. Mobile commita820543recordsITSAppUsesNonExemptEncryption=falsefor the iOS build's exempt-encryption declaration. Android EAS development-build profiles/checklist exist from mobile PR-12, but Android manual QA is held unless the operator reopens that lane. Product launch scope is Heathrow-only.
Target Presence Workflow (boarding-pass gate)¶
This is the product source of truth for how a traveler enters the airport social
graph (PD-012). The backend /presence contract is implemented, mobile PR-15
implements the gate/lock shell, mobile PR-16 implements the camera-scan capture/
decode/confirm/create path, and mobile PR-17 implements Photos/Files image import
through the same path. Mobile PR-18 physically verifies the iPhone product path
using a safe synthetic boarding-pass barcode and image import; no real pass
payload or passenger data is retained in Tier 1 evidence.
Workflow:
- Sign in - LinkedIn OIDC, as today.
- Boarding-pass gate - presence/matching/candidates/conversations are locked until a verified trip exists. There is no skip and no manual flight-entry fallback in the product flow. Implemented as UI/state gate in mobile PR-15.
- Scan / import - the traveler provides a boarding pass via in-app capture. Camera scan is implemented in mobile PR-16. Image/screenshot import from Photos/Files is implemented in mobile PR-17. PDF/document import is not decoded today and must fail closed unless a later local, no-retention decoder is added.
- Barcode decode - the app/backend decodes the boarding-pass barcode (IATA BCBP payload over PDF417 / Aztec / QR / Data Matrix) as the verification source. Mobile PR-16/PR-17 parse the barcode on-device and keep only origin airport, optional destination display, optional carrier/flight, and a conservative TTL. OCR may only label fields when barcode extraction fails; it is never the verification source.
- Confirm normalized trip - the traveler confirms the decoded, normalized trip (airport, optional destination/flight, derived window) before anything is created. Implemented for camera scan in mobile PR-16 and image import in mobile PR-17.
- Create presence - a confirmed trip submits the normalized fields to the
backend product
/presenceroute withverification_source=boarding_pass_barcodeandverification_level=document_verified. Implemented for camera scan in mobile PR-16 and image import in mobile PR-17. - Unlock - matching, candidates, and conversations become available for that verified trip. Mobile PR-18 verified that the lock/gate disappears after confirmation; no candidates being present is acceptable empty data, not a lock failure.
Accepted MVP inputs (in-app capture):
- Camera scan of a paper boarding pass.
- Camera scan of another screen showing a digital boarding pass.
- Import of a screenshot/image from Photos or Files. PDFs/documents are currently unsupported and fail closed with sanitized copy.
Explicitly non-MVP inputs (named so they are not assumed):
- Manual flight entry - excluded from the product flow entirely, not even a default fallback.
- Direct iOS/Android share extension ("share to Partile") - later work; needs extra native share-extension/intent surface, deferred until the core gate is proven.
- Direct Apple Wallet (pass-library) access - not a product dependency. If a
user can export/share a screenshot or image into the app, that is an ordinary
import input; reading the Wallet pass library directly is not assumed. Direct
Google Wallet access is treated the same way.
.pkpassand PDF decoding remain unsupported in the current mobile app.
Data boundary: raw image/PDF/barcode material is transient and not retained;
only minimal normalized trip/presence fields needed for matching and safety are
stored (see ../technical/data-architecture.md and PRIV-06). Boarding-pass
processing legal basis / minimization / retention is queued for counsel at C25.
Current Product Assumptions¶
- Partile is professional-networking-only. Dating/casual framing is out of scope (PD-013).
- Matching requires verified shared place and time: boarding-pass-derived airport X plus window W. A night-before scan can enter tomorrow's pool; no proximity in both place and time means no match (PD-014).
- Discovery is an open, relevance-ranked directory of everyone in-window, with starring/shortlist workflow. Backend directory/ranking and mobile local-only stars are implemented (PD-015).
- Request-to-connect with a note supersedes approve/dismiss double-opt-in as the product model. The recipient reads the note before accepting or declining (PD-016).
- Match rationale is model-generated and symmetric: both sides see the same "why you two." Backend rationale is implemented key-gated through Claude and cached by minimized pair inputs. PDL/ZoomInfo enrichment is internal matching input only and must not be displayed or redistributed (PD-017).
- Profile input can include LinkedIn, optional internal enrichment, quick intent tags, and an optional AI interview. Profile edit and the backend AI interview endpoint are implemented; mobile interview UI remains upcoming. MVP AI scope is match rationale plus AI profile interview only; no AI icebreakers or scheduling (PD-018).
- Structured chat is a working assumption: request note opens, recipient confirms intent (Advice / Intro / Hiring / Pitch / Just connect), then one-tap Propose-to-meet reveals gate/area and a suggested neutral Heathrow spot only on mutual accept (PD-019).
- Persistent connections are a working assumption: accepted professional
connections persist after the trip, while discovery remains window-bound
(PD-020). Backend
GET /connectionsimplements the contacts list, with retention duration still pending C28 (PD-025). - Launch is Heathrow-only until the operator explicitly expands launch scope (PD-021).
- Message-send is in product scope. Message events should record metadata only,
such as length and identifiers needed for lineage, never message body. Backend
PR-22 implements this as
message.sentT1 metadata only (PD-022). - AI match rationale and the optional AI profile interview use the real Claude
API. Anthropic is an integrated, key-gated subprocessor: absent a key,
rationale degrades to null and
/profile/interviewreturns 503. The built controls preserve no-training/provider controls, minimization, and bounded response caching for rationale; interview output is advisory and not written to the profile automatically (PD-023). - Enrichment is deferred. PDL/ZoomInfo remain planned, not contracted, and no broker data is processed until a later explicit vendor/implementation decision. Ranking should use internal signals only for now (PD-024).
- Consent is captured with separate optional toggles for analytics, ML training, and marketing in Settings, with a Home first-run prompt for users who have never set a grant. Core matching should continue without analytics/ML/marketing grants.
- Consent copy and notice labels may use internal placeholder text before real users; final external text is legal/policy publication work.
- Deleted-user sent messages should be tombstoned, preserving thread continuity for the other participant, unless later product/counsel review changes this.
- Reports against deleted users should be retained in a pseudonymized safety form for the report-retention window.
- Product is 18+ until an age/minors policy exists.
- Safety guidance should appear before first meaningful in-person contact.
- Worker lifecycle events start as analytics-tier, worker-originated, actor-scoped rows per affected participant unless a later product decision makes them ML-training signals or pair-wide events.
- Message events should record metadata only, such as length and identifiers needed for lineage, never message body.
- Future ML training uses anonymized aggregate snapshots from whitelisted T2
events only. Direct
app_events, T0/T1 events, low-k groups, raw trajectories, and non-whitelisted fields are not training inputs; counsel still ratifies the final anonymization standard before real model training. - A verified boarding pass is required to create presence; manual flight entry is
not a product path (PD-012). The backend now enforces this at
/presence, and mobile PR-15 removes the manual presence path. Mobile PR-16 implements camera barcode decoding and sanitized confirmation; mobile PR-17 implements image import through the same verification source; mobile PR-18 physically verifies the scan/import/unlock path on iPhone. The verification source is barcode decoding, not OCR. - Raw boarding-pass image/PDF/barcode material is transient and not retained; the backend persists only minimal normalized trip/presence fields.
- Share-to-Partile extensions, PDF decoding, and direct Wallet pass-library access are later work, not MVP; in-app camera scan plus screenshot/image import is the current MVP capture path.
Upkeep¶
This file must be checked on every pass. If the passed PR changes the product
surface or resolves/creates a product assumption, update this file and
product-decisions.md in the data-room worktree as a consistency amendment.
No secrets, PII, raw tokens, raw cloud output, account IDs, legal advice, or external policy text belongs here.