# Optional fields in public app packets

## Packet 0.4 at the existing URLs

Each independent `storeObservations` item may include `downloadPrice: { amount: 0, currency: "USD" }` and `inAppPurchases: true` or `false`. Omitted means not established. Zero is the download price, not a claim that all features are included. `commerceEvidence.downloadPrice` and `commerceEvidence.inAppPurchases` each identify the exact source URL and successful `observedAt` date. These dates may precede the listing's latest successful refresh when a later response did not establish the fact. Platform and geography belong to that observation; do not apply one store's facts to another. Subscription detection is not provided. Version 0.3 retains its original store observation fields without commerce additions.

For registered iOS apps, Blue Jetty looks up Apple's primary App Store category after submission and uses it as `app.category`. Optional `app.categoryEvidence` identifies the store source and observation time. This observation is separate from publisher assertions and authorization; it does not advance the publisher's content revision. App Store ID and bundle ID must both match. A failed lookup preserves the last matching observation, and changing either store identity prevents reusing it. Without a matching observation, the existing category remains the fallback. Entity content types are not app categories.

The default packet uses wire `specVersion: "0.4"`. JSON and Markdown expose the same current data. `protocol` identifies the [explanation](/for-ai), [service metadata](/protocol.json) and [publication schema](/schemas/packet/0.4/schema.json). Version 0.4 adds independently dated download price and IAP evidence. Select retained versions with `Blue-Jetty-Packet-Version: 0.3`, `Blue-Jetty-Packet-Version: 0.2` or `0.1`. Neither this version nor publisher configuration 0.5 changes the packet URL, proof binding or discovery descriptor.

### Independent store observations

`storeObservations` publishes already-retained store facts separately from publisher assertions. The same projection is included in publisher-backed `/v1/index/apps/{publicId}` and `/v1/apps/{appId}` JSON. Each entry identifies its platform, listing, source URL, observation time and geography. When captured, entries include the full store description, category, developer and developer identifier, average rating on a five-point scale, rating count, version, source-reported update date and normalized Apple device compatibility. Missing optional values are omitted; an empty array means no matching retained observation.

Apple ratings describe the observed storefront. Google ratings describe the public listing response, not a verified country-specific aggregate. Never combine platform ratings or interpret `ratingCount` as downloads. `observedAt` is the last successful full listing observation; `sourceUpdatedAt` is the store's reported release/update date. Failed refreshes preserve the last matching observation and its actual date. Reads do not fetch the stores or make old evidence fresh. Listing retrieval does not establish worldwide availability or device install eligibility. Publisher descriptions, authorization and publication revisions remain separate.

- `representationPreferences.publisherStatements`: attributed publisher text with its original source field and optional intent/destination/campaign scope. Legacy prose is retained as source data, not silently rewritten or promoted to instructions.
- `representationPreferences.recommendationEligibility`: an explicit publisher assertion when supplied. Missing eligibility is unknown. Relevance remains the consuming system's decision.
- `preferredRepresentation.preferred`: the current selected URL; `urlSemantics` distinguishes fixed parameters from explicitly permitted recipe bindings.
- `handoffSummary`: a compact declarative view with the actual general URL, separate iOS/Android targets and specific-experience endpoint templates. `selectionSource` distinguishes publisher preferences/destinations from website or platform-store fallbacks. For legacy records without an explicit preference, an unknown platform uses the submitted, currently authorized ordinary website; a known platform uses its store link. No eligible neutral URL means `platform_required`, without choosing Apple or Google by ordering. Existing configured MMP and destination selection is preserved.
- `releaseStatus.scope`: `release_version_comparison_not_app_availability`. A platform's `baseline_not_supplied` status means the publisher has not supplied its release-version baseline to Blue Jetty. It makes no statement about store availability, discovery or authorization. The retained `indexed` field is that baseline; `store` is the separate dated version observation. Legacy packet 0.1 retains its older labels.
- `handoffSemantics`: platform/install-state eligibility, publisher routing preference and provider parameter meanings. Recipes retain finite choices, exactly-once encoding, fixed URL bytes and fallbacks.
- `app.publisherAuthorization`: existing app-specific authorization and scoped store/domain relationship evidence. The ambiguous legacy `app.verificationStatus` is absent. Legacy app-record/entity APIs retain their historical catalog field with a scope explanation; that field is not authorization.
- `discovery.sourceConfigurationVersion`: the source input version, independent of this filtered publication shape. `publication.version` tracks publisher history, not format changes.

No default `machineInstructions`, `Publisher instructions` section or generated recommendation command is emitted. Implementation prompts still require human review and approval before publishing.

### Compatibility and rollback

Existing configuration inputs 0.2–0.4 remain accepted and stored unchanged. Configuration 0.5 replaces basic/advanced instruction fields with `representation.summary`, optional `recommendationEligibility` and scoped `preferences`. Publisher-approved migrations use the existing preview, revision diff and activation flow; no automatic text rewrite occurs.

Entity feeds retain their independently versioned 0.1 contract. A feed's `discovery` field retains the published configuration-shaped projection, including legacy source field names. The packet is the current consumption view with explicitly attributed publisher statements and handoff semantics; its `discovery` field is not interchangeable with a feed or an owner configuration.

A client can request `Blue-Jetty-Packet-Version: 0.1` for legacy JSON/Markdown and handoff representations, or `0.2` for the current format. Unsupported values return 400. The default requires no header or new URL. Responses remain no-store, vary by the version header and User-Agent, and rebuild current authorized data before ETag comparison. A proxy needs explicit forwarding only for non-default version selection. Static copies require regeneration at their existing URLs. Legacy retirement is a separate decision.



Retrieve `/v1/apps/{appId}/packet` for JSON or `/v1/apps/{appId}/packet.md` for Markdown. Both formats publish the same currently authorized app context.

## Interpreting missing information

An omitted optional field means **no information is supplied in this packet**. It does not establish that the app lacks an offer, attribution provider, platform or feature. Do not infer the publisher's subscription tier from missing fields.

- `currentPromotion` appears only when a publishable promotion blurb exists. Its `updatedAt` is omitted when unavailable.
- `preferredRepresentation.attribution` appears only when attribution information is available for the selected handoff. Optional null attribution fields are omitted.
- Unavailable preferred handoffs, handoff update timestamps and platform identifiers/store URLs are omitted.
- Empty optional discovery collections (`promotions`, `destinations`, `intents`, `platformDefaults`) are omitted. Platform defaults without attribution are omitted. Recipe guidance appears only when a published execution includes a recipe.
- Explicit unknown values in authorization, revision, release and execution evidence retain their existing meanings. Values such as `false` and `0` are preserved. This is not a blanket removal of every null or empty collection.

For example, a packet with no published promotion has no `currentPromotion` key. A supplied promotion is represented as:

```json
{
  "currentPromotion": {
    "blurb": "Eligible new members can use WELCOME for the publisher's introductory offer."
  }
}
```

This is an illustrative fragment, not a complete packet. `"currentPromotion": null` is no longer emitted; consumers should tolerate omitted fields and historical nullable responses during migration.

## App entitlements and publication

Blue Jetty resolves entitlements server-side for the publisher app and organization before producing either format. Configured acquisition features publish only when their applicable entitlement permits them. Active pilot access is independent of payment and continues to permit eligible features. Public packets do not expose the account's billing state.

Expired or inactive structured offers are excluded. Downgrading preserves stored publisher configuration while removing restricted content from the public projection. Where platform-scoped licensing still applies, the existing platform entitlement checks remain in effect; this change does not migrate billing or activate charges.

Core retains the app's capabilities, experience descriptions, relevance instructions, website/store destinations and fixed native/MMP links. Growth controls link recipes, structured offers and their lifecycle, automatic Apple App Store version monitoring and expanded analytics access. The complete dashboard remains available for the last 30 days.

If an experience has only Growth-gated executions, its public projection may use the publisher's canonical website as a general fallback (`kind: "web"`, execution ID `core-website-fallback`). This describes a website visit, not a verified opening of that in-app screen. Saved managed links remain in the private owner configuration. Known attribution-provider URLs cannot serve as the free canonical fallback. Omitted offers and routes still mean no information is supplied, not that the app has none.

Blue Jetty rebuilds the current projection before evaluating a conditional request. JSON and Markdown use content-specific ETags and `no-store` headers, including CDN headers. An old ETag cannot validate changed content after an entitlement change. Third-party caches and downloaded copies remain outside Blue Jetty's control; proxies must honor the [first-party delivery rules](/developers/first-party-delivery.md).

## Publisher updates and compatibility

These rules apply to public packet output only. Owner-facing status and configuration retain explicit state. Submission schemas, clear/reset operations and their existing `null` semantics are unchanged. Use owner-authorized configuration/history endpoints for editing; the filtered packet's `discovery` object is not a complete resubmittable configuration.

Coding agents should preserve meaningful `false`, `0`, extension values and documented evidence unknowns. Never infer that an omitted public value should be cleared from stored configuration. See [maintenance](/developers/maintenance.md) for safe updates and version preconditions.

## Summary interpretation

`provenanceSummary` summarizes current `app.publisherAuthorization` and its actual relationship evidence methods (`store_lookup`, `operator_review`, or both). The existing authorization object retains scope, sources and timestamps. Publisher descriptions, capabilities, use cases and offers remain publisher claims unless separately evidenced; authorization is not independent verification of every claim.

`handoffSummary.statusScope` limits its status to general destination selection. It does not establish installed-device opening or attribution readiness. `urlHandlingExplanation` states the fast-path rule: returned URLs stay unchanged; only an explicit link recipe permits its declared substitutions. The existing `urlHandling` value and detailed URL/recipe semantics remain unchanged.

Omitted optional fields mean information was not supplied **in this packet**. They do not establish that the app lacks a capability, offer, MMP or deep link, or reveal its entitlement. Rich inventories remain available through the existing entity/feed URLs and scoped handoff templates; the summary does not embed the inventory.

These summaries are additive publication-schema 0.2 fields. Existing field paths, status enums, URLs, publisher configuration and legacy 0.1 output are preserved. Consumers must not rely on JSON property order.
## Core MMP and Growth offers

Fixed publisher MMP/native links and their existing parameters remain available in Core. Growth filters apply to recipes and structured offers, without deleting saved configuration. Supported offer bindings add `discovery.promotions[].handoff` with a ready-to-use `url`, fixed fallback, platform/install-state scope and publisher-reviewed binding status. See [offers](/developers/offers.md); binding syntax does not verify device arrival or redemption. Automatic Apple store observations are separately sourced and available with Growth monitoring.
## Experience summaries and compact catalog views

The existing packet URLs serve schema 0.4 by default and retain explicit 0.2 selection. `discovery` contains configured capabilities/intents/destinations; optional `experienceSummary` brings accepted published entity descriptions into the same first retrieval. These are two publisher-source views, not independent corroboration. The summary uses stable entity IDs and native-ID order, up to 24 entries and 24,000 UTF-8 bytes for the item array. Each title is bounded to 240 characters and each summary to 1,600. This is Blue Jetty's engineering budget, not a crawler limit.

Optional summary `attributes` contains up to six already-public scalar attributes in key order, with keys up to 100 characters and complete string values up to 300. Canonical `{value, unit, vocabulary, language}` wrappers retain their supplied metadata and units. Longer values, arrays and other nested objects remain in the linked record; `attributesTruncated` identifies omissions. Do not treat this bounded selection as a complete list of conditions or features. The same public authorization and publication filters apply before projection.

`total`, `returned`, `truncated` and per-item `textTruncated` describe completeness. Follow each `url` for the full experience or `detailsUrl` for paginated JSON. The source is `published_app_records`; each item's `provenance` retains the recorded source classification rather than turning imported material into independently verified facts. Source IDs, publisher source dates when supplied, and record update dates retain their meanings; rendering does not renew assertions. Omitted summaries do not establish absent capabilities. JSON and Markdown share the same source projection; Markdown includes escaped readable descriptions alongside structured facts. `app.identifiedPlatforms` reflects supplied identifiers/store URLs; fallback destinations for other platforms do not establish support for them.

Empty `representationPreferences`, `executionEvidence`, and provider lists are omitted. `releaseStatus` is present only with a supplied baseline or observation, and only for those platforms; it is a comparison, not an availability verdict. `preferredRepresentation` retains its existing public name for compatibility and means the preferred user destination. `handoffSummary` is its concise consumption view. Full protocol meanings remain available in `/protocol.json` and `/for-ai`. Explicit packet version 0.1 remains unchanged.

`GET /v1/apps` now returns a compact `bluejetty.packet_index/1` listing of identities, brief descriptions, packet links and update times, up to 100 apps per page. Follow `meta.next` (also HTTP `Link: rel=next`) until null. `limit` is 1–100 and `after` is a returned stable app ID. The former detailed app projection is available at `?view=records&limit=100&offset=0`, also bounded. Individual app records remain at `/v1/apps/{appId}`. Re-fetch listings to observe withdrawals; listings are not historical snapshots.

Entity GET endpoints default to scoped provenance without numerical ranking scores or ambiguous global verification labels. `?view=legacy` retains the previous entity projection. Version-0.1 JSON/JSONL feeds retain their separately versioned shape. Search scores remain retrieval diagnostics, not publisher assertions. No private/sample/unauthorized records are added by these views.
