From a77901e749766a6bfe051c9c7d8eec918965f9e4 Mon Sep 17 00:00:00 2001
From: Hyo
Date: Thu, 13 Aug 2026 06:42:15 +0900
Subject: [PATCH 1/3] docs: refine ecosystem and writing workflows
---
.claude/commands/commit.md | 4 +-
.claude/skills/loop-review/SKILL.md | 18 +
.codex/skills/generate-doc/SKILL.md | 41 +-
.codex/skills/generate-doc/agents/openai.yaml | 2 +-
.codex/skills/loop-review/SKILL.md | 129 +++++
.codex/skills/loop-review/agents/openai.yaml | 4 +
.codex/skills/openiap-workflows/SKILL.md | 7 +-
.cursor/rules/openiap-ssot.mdc | 15 +
AGENTS.md | 33 +-
knowledge/README.md | 1 -
knowledge/_claude-context/context.md | 296 ++---------
knowledge/internal/05-docs-patterns.md | 51 ++
knowledge/internal/08-gv-cloud-workspaces.md | 237 ---------
.../docs/src/components/EcosystemDiagram.tsx | 88 +++-
packages/docs/src/lib/images.ts | 14 +
.../src/pages/docs/setup/store/onside.tsx | 7 +-
.../docs/src/pages/docs/updates/releases.tsx | 475 +++++-------------
.../docs/src/styles/ecosystem-diagram.css | 143 +++++-
18 files changed, 684 insertions(+), 881 deletions(-)
create mode 100644 .claude/skills/loop-review/SKILL.md
create mode 100644 .codex/skills/loop-review/SKILL.md
create mode 100644 .codex/skills/loop-review/agents/openai.yaml
create mode 100644 .cursor/rules/openiap-ssot.mdc
delete mode 100644 knowledge/internal/08-gv-cloud-workspaces.md
diff --git a/.claude/commands/commit.md b/.claude/commands/commit.md
index 9230f5d5c..72ae20dc4 100644
--- a/.claude/commands/commit.md
+++ b/.claude/commands/commit.md
@@ -47,8 +47,8 @@ Inspect the complete commit message, PR title, and PR body before sending them.
If the staged changes only touch internal agent/workflow files, do not push or
create a PR unless the user explicitly asked to publish, PR, or merge them.
Internal workflow files include `.claude/commands/`, `.claude/skills/`,
-`.codex/skills/`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, and agent
-automation notes.
+`.codex/skills/`, `.cursor/rules/`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, and
+agent automation notes.
For those internal-only changes, prefer a local commit or local working-tree
change and report the files changed. If the user explicitly asks to open or
diff --git a/.claude/skills/loop-review/SKILL.md b/.claude/skills/loop-review/SKILL.md
new file mode 100644
index 000000000..f1cdc5b77
--- /dev/null
+++ b/.claude/skills/loop-review/SKILL.md
@@ -0,0 +1,18 @@
+---
+name: loop-review
+description: "Run OpenIAP's complete latest-main-to-merge review loop: review-self, commit and PR, five-minute CodeRabbit and CI polling, fixes, verification, and clean-head merge."
+---
+
+# Loop Review (Claude Code)
+
+The canonical workflow lives in `.codex/skills/loop-review/SKILL.md`. Read that
+file first and follow it fully.
+
+Use Claude Code's matching skills or commands for each delegated phase:
+
+- `/review-self` for pre-PR stabilization and exact-head fallback review.
+- `/commit --all --pr` for commit, push, PR, labels, and preview.
+- `/review-pr ` for review threads, CodeRabbit, CI polling, and cleanup.
+- `ScheduleWakeup` for every five-minute re-entry; never use a shell sleep loop.
+
+Do not merge until the canonical exact-head clean gate is satisfied.
diff --git a/.codex/skills/generate-doc/SKILL.md b/.codex/skills/generate-doc/SKILL.md
index a8cee4c93..874f41e35 100644
--- a/.codex/skills/generate-doc/SKILL.md
+++ b/.codex/skills/generate-doc/SKILL.md
@@ -59,10 +59,10 @@ Before adding a release card, inspect the newest entries and package tags.
belong to the same release train, expand that card into the single
consolidated release entry and advance its date and title. Do not create a
second card for the package versions.
-- Structure a consolidated train in this order: a short `Common changes`
- summary, hosted IAPKit changes, versioned native and framework changes grouped
- by package, migration or integration notes, and `Package Releases` at the
- bottom (see the exact card layout in Editing Release Notes).
+- Use only sections with distinct user-visible behavior or required action.
+ Keep any shared summary first, affected native and framework notes next,
+ migration or integration action after them, and `Package Releases` at the
+ bottom (see Editing Release Notes).
- IAPKit and its MCP deploy as services and have no package version. Include
their user-visible behavior in the consolidated card, but never invent an
IAPKit item in the versioned `Package Releases` list.
@@ -152,22 +152,34 @@ Follow the existing card pattern:
Card section layout (mandatory for multi-package cards):
-- Use `h5` headings only for shared groups, in this order: `Common changes`
- (optional), `Shared spec and native packages`, `Framework libraries`,
- `Integration notes` (or migration notes), then the bordered
- `Package Releases` block.
+- Use only the sections that contain information readers must act on. Keep them
+ in this order when present: `Common changes`, `Shared spec and native
+ packages`, `Framework libraries`, `Integration notes` (or migration notes),
+ then the bordered `Package Releases` block.
- Never add one `h5` heading per platform or framework (no `Apple`, `Google`,
- `React Native`, `Expo`, ... headings). Each package's changes are exactly one
- `
` inside the shared group list, written as
+ `React Native`, `Expo`, ... headings). Each package-specific behavior gets at
+ most one `
` inside the shared group list, written as
`package version - prose description`
(for example `react-native-iap 16.0.2 - exposes ...`).
- `Shared spec and native packages` holds `OpenIAP Spec`, `openiap-apple`, and
`openiap-google` bullets; `Framework libraries` holds the framework SDK
- bullets. Omit a bullet entirely when that package has no user-facing change.
+ bullets. Omit the section when it would be empty.
+- A package whose only change is selecting a shared native dependency,
+ regenerating types, or republishing the same behavior belongs only in
+ `Package Releases`. Do not manufacture one boilerplate bullet per wrapper.
+- One bullet may name multiple packages when the same user-visible behavior and
+ caveats apply to all of them. Keep distinct behavior in distinct bullets.
- The July 29, 2026 card (`openiap-major-api-cleanup-2026-07-29`) and the
August 4, 2026 card (`amazon-rvs-user-data-patch-train-2026-08-04`) are the
reference implementations of this layout.
+## Reader-First Writing Standard
+
+Apply the canonical standard in
+`knowledge/internal/05-docs-patterns.md#reader-first-writing-standard` to every
+new or edited release card. Render the result and remove repeated facts,
+wrapper-only dependency boilerplate, and sections with no reader action.
+
## Multi-package Release Trains
The consolidated release page remains the release-note SSOT, but a release that
@@ -180,9 +192,10 @@ project decision recorded from issue #206.
- Group notable changes under the affected platform package or framework
library (Google, Apple, IAPKit, React Native, Expo, Flutter, Godot, KMP, and
MAUI). Omit groups with no user-facing change.
-- Keep each group concise. State the behavior users gain or the regression that
- was fixed; do not list commit mechanics, version-bump-only commits, generated
- files, or repeated cross-framework boilerplate.
+- Apply the Reader-First Writing Standard above. State the behavior users gain
+ or the regression that was fixed; do not list commit mechanics,
+ version-bump-only commits, generated files, or repeated cross-framework
+ boilerplate.
- Put truly shared schema or release-process changes in one short shared group,
then describe framework-specific wiring or caveats in the relevant framework
group.
diff --git a/.codex/skills/generate-doc/agents/openai.yaml b/.codex/skills/generate-doc/agents/openai.yaml
index 3d10a6b06..e17201097 100644
--- a/.codex/skills/generate-doc/agents/openai.yaml
+++ b/.codex/skills/generate-doc/agents/openai.yaml
@@ -1,4 +1,4 @@
interface:
display_name: "Generate OpenIAP Docs"
short_description: "Document expected releases without duplicate trains"
- default_prompt: "Use $generate-doc to update the existing unreleased OpenIAP card in place with common changes, per-package native and framework notes, and expected Package Releases links at the bottom."
+ default_prompt: "Use $generate-doc to update the existing unreleased OpenIAP card with concise user-visible changes for affected packages and the verified Package Releases links."
diff --git a/.codex/skills/loop-review/SKILL.md b/.codex/skills/loop-review/SKILL.md
new file mode 100644
index 000000000..d0c42ea31
--- /dev/null
+++ b/.codex/skills/loop-review/SKILL.md
@@ -0,0 +1,129 @@
+---
+name: loop-review
+description: "Run OpenIAP's complete change-to-merge loop from the latest origin/main: create a semantic branch, implement and verify the requested change, run review-self until stable, commit and open a PR, poll CodeRabbit and CI every five minutes, fix and reverify findings, and merge only when the exact head is clean. Use when the user invokes $loop-review or explicitly asks for the recurring review-self, commit --pr, review-pr until clean, then merge workflow."
+---
+
+# Loop Review
+
+Own one OpenIAP change from a fresh `main` baseline through a verified merge.
+Use the repository workflows as SSOT instead of duplicating their detailed
+commands.
+
+## Load The Workflows
+
+Read these before acting:
+
+- `AGENTS.md`
+- `.codex/skills/openiap-workflows/SKILL.md`
+- `.codex/skills/review-self/SKILL.md`
+- `.claude/commands/commit.md`
+- `.claude/commands/review-pr.md`
+
+Load package conventions and specialized skills required by the changed paths.
+An explicit `$loop-review` invocation or explicit natural-language request for
+this complete loop authorizes the in-scope commit, push, PR, review replies,
+thread resolution, and merge. It does not authorize deployment, publication,
+release, or unrelated cleanup.
+
+## 1. Start From Current Main
+
+Before editing task files:
+
+1. Snapshot `git status --short --branch`. Preserve every existing change.
+2. For a new task, require a clean worktree, then run `git fetch origin`, switch
+ to `main`, and run `git pull --ff-only origin main`.
+3. Verify local `main` equals `origin/main`, then create a semantic branch named
+ according to `.claude/commands/commit.md`.
+4. Record the starting main SHA. The implementation diff must descend from that
+ SHA.
+
+Never start new implementation on a stale local `main`. If invoked for work
+already in progress, do not manually switch branches, stash, reset, or discard
+it. Treat that as a resumed loop, verify its recorded or merge-base baseline,
+and use the repository's guarded `rebase-main` workflow when an update from
+`origin/main` is needed; that workflow owns its safeguard stash and branch
+transitions. Stop for direction if an update would overwrite unrelated user
+work.
+
+## 2. Implement And Verify
+
+Implement the requested scope and run the checks required by each touched path.
+Keep generated files, documentation, previews, and knowledge context in sync
+through their canonical workflows. Do not proceed while the working diff has a
+known failing required check.
+
+## 3. Stabilize With Review Self
+
+Run `$review-self` immediately against the complete base-to-working-tree diff.
+Fix every validated in-scope finding and rerun affected verification. Continue
+with five-minute recurring wake-ups until two consecutive complete snapshots are
+clean, as defined by the review-self skill.
+
+Do not emulate recurring review with a shell sleep loop. Keep the loop state out
+of tracked files. Any material diff change resets the consecutive-clean count.
+
+## 4. Commit And Open The PR
+
+Follow `.claude/commands/commit.md --all --pr`:
+
+- Stage only files owned by the task.
+- Use the required commit order and an English conventional commit message.
+- Push the semantic branch and open an English PR against `main`.
+- Add applicable repository labels.
+- For a visible or interactive change, attach a preview recording under 10 MB.
+ Do not commit one-off preview media unless browser upload is blocked and the
+ documented fallback is required.
+
+Record the PR number and exact head SHA. A push invalidates all prior clean
+review coverage.
+
+## 5. Review PR Until The Exact Head Is Clean
+
+Run `.claude/commands/review-pr.md` immediately, then re-enter it every five
+minutes through the product's recurring wake-up mechanism.
+
+For every round:
+
+1. Fetch unresolved threads, review status, current head SHA, and required CI.
+2. Fix all valid findings in one coherent batch; push, reply to the exact inline
+ comments, and resolve only fixed or outdated threads under the command rules.
+3. Rerun the checks affected by the batch plus all previously failing checks.
+4. Request CodeRabbit again after a head change.
+5. If CodeRabbit is unavailable, use the exact-head one-pass `$review-self`
+ fallback defined by `review-pr`; never substitute another reviewer.
+6. Keep polling while review or CI is pending. Do not rerun expensive unchanged
+ local checks on a no-op poll.
+
+Clean means all of the following hold for the same head SHA:
+
+- zero unresolved actionable review threads;
+- CodeRabbit is clean, or its unavailable result has clean review-self fallback
+ coverage;
+- every required CI check is terminal and successful or explicitly allowed to
+ skip by repository policy;
+- the PR is mergeable and the branch contains every required update from main;
+- the worktree is clean and the final diff has been reread.
+
+## 6. Merge And Close The Loop
+
+Immediately before merging, refetch the PR and confirm its head still equals the
+clean reviewed SHA. Use the repository-supported merge method, defaulting to a
+squash merge with branch deletion when no stricter policy applies. Never bypass
+branch protection or merge a stale, pending, or failing head.
+
+After merge:
+
+1. Confirm the PR state is `MERGED` and record the merge commit.
+2. Remove temporary review-trigger and terminal-unavailability comments as
+ required by `review-pr`.
+3. Switch to `main` and fast-forward from `origin/main` only when doing so cannot
+ disturb other work.
+4. Report the PR, merge commit, final checks, review coverage, and any skipped
+ item. Do not deploy or release unless separately requested.
+
+## Stop Conditions
+
+Stop without merging when a required choice lacks authority, the same finding
+survives two fix attempts, an access blocker repeats under the source workflow's
+threshold, or the exact head cannot satisfy the clean gate. Report the concrete
+blocker; never describe a pending or partially reviewed PR as clean.
diff --git a/.codex/skills/loop-review/agents/openai.yaml b/.codex/skills/loop-review/agents/openai.yaml
new file mode 100644
index 000000000..17a8d8617
--- /dev/null
+++ b/.codex/skills/loop-review/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Loop Review"
+ short_description: "Review, publish, and merge a clean OpenIAP change"
+ default_prompt: "Use $loop-review to start from the latest origin/main, stabilize the change, open a PR, address reviews, and merge it."
diff --git a/.codex/skills/openiap-workflows/SKILL.md b/.codex/skills/openiap-workflows/SKILL.md
index f7b4a8ff7..2b12ee44a 100644
--- a/.codex/skills/openiap-workflows/SKILL.md
+++ b/.codex/skills/openiap-workflows/SKILL.md
@@ -58,9 +58,10 @@ platform rows, connected-device rows, and explicit blocked/unsupported rows.
## Internal Workflow Change Guard
Internal agent/workflow-only changes include `.claude/commands/`,
-`.claude/skills/`, `.codex/skills/`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`,
-and agent automation notes. Do not create a branch, push, or open a PR for
-those changes unless the user explicitly asks to publish, PR, or merge them.
+`.claude/skills/`, `.codex/skills/`, `.cursor/rules/`, `AGENTS.md`,
+`CLAUDE.md`, `GEMINI.md`, and agent automation notes. Do not create a branch,
+push, or open a PR for those changes unless the user explicitly asks to publish,
+PR, or merge them.
If a user asks to update an internal workflow and does not explicitly ask for a
PR, keep the change local and report the changed files. If a PR is already open
diff --git a/.cursor/rules/openiap-ssot.mdc b/.cursor/rules/openiap-ssot.mdc
new file mode 100644
index 000000000..317d7546b
--- /dev/null
+++ b/.cursor/rules/openiap-ssot.mdc
@@ -0,0 +1,15 @@
+---
+description: OpenIAP repository instruction routing
+globs:
+alwaysApply: true
+---
+
+- Treat `AGENTS.md` as the root project instruction SSOT. `CLAUDE.md` and
+ `GEMINI.md` are symlinks to it; do not maintain separate copies.
+- Before editing a package or library, read the relevant files linked from
+ `AGENTS.md`.
+- For any user-facing documentation, apply
+ `knowledge/internal/05-docs-patterns.md#reader-first-writing-standard` and the
+ package convention. Keep prose concise, actionable, and free of repetition.
+- Keep detailed rules in their canonical files. This Cursor adapter only routes
+ to them.
diff --git a/AGENTS.md b/AGENTS.md
index bb3b69e13..6592df69e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -15,7 +15,6 @@ This document provides an overview for AI agents working across the OpenIAP mono
| Docs Patterns | [`knowledge/internal/05-docs-patterns.md`](knowledge/internal/05-docs-patterns.md) |
| Git & Deployment | [`knowledge/internal/06-git-deployment.md`](knowledge/internal/06-git-deployment.md) |
| Docs Consistency / SSOT | [`knowledge/internal/07-docs-consistency.md`](knowledge/internal/07-docs-consistency.md) (run `bun audit:docs` before pushing API/Type doc edits) |
-| GV Cloud Workspaces | [`knowledge/internal/08-gv-cloud-workspaces.md`](knowledge/internal/08-gv-cloud-workspaces.md) |
## Monorepo Structure
@@ -89,6 +88,16 @@ well-known APIs. Keep only what the code cannot show: platform quirks, non-obvio
constraints, and why an obvious alternative was rejected. Full checklist in
[`knowledge/internal/03-coding-style.md`](knowledge/internal/03-coding-style.md#keep-them-short--especially-ai-generated-ones).
+### Reader-First Documentation
+
+Write every user-facing document for scanning and action. Lead with the outcome,
+state each fact once, and remove filler, implementation narration, repeated
+cross-package boilerplate, and detail that does not change user behavior. Keep
+required compatibility, migration, safety, and platform caveats. Apply the
+canonical standard in
+[`knowledge/internal/05-docs-patterns.md`](knowledge/internal/05-docs-patterns.md#reader-first-writing-standard),
+including its stricter release-note limits.
+
### Platform Function Naming
- **iOS functions**: Must end with `IOS` suffix (e.g., `syncIOS`, `getReceiptDataIOS`)
@@ -205,9 +214,9 @@ Codex-compatible local skills in `.codex/skills/`, including
`openiap-workflows` for mapping Claude slash-command workflows and `review-self`
for repeated self-review of current work.
-Codex discovers `review-self` from this repository. Install the globally unique
-skills (`openiap-workflows` and `generate-doc`) into your local Codex home when
-needed:
+Codex discovers `review-self` and `loop-review` from this repository. Install
+the globally unique skills (`openiap-workflows` and `generate-doc`) into your
+local Codex home when needed:
```bash
./.codex/scripts/install-skills.sh
@@ -217,9 +226,9 @@ After installation, ask Codex normally (for example, "review PR 65" or
"resolve issue 88"), or explicitly mention `$openiap-workflows` or
`$review-self`.
-Keep `$review-self` repo-local. Other repositories provide project-specific
-skills with the same name, so globally linking it would make the most recently
-installed project overwrite the others.
+Keep `$review-self` and `$loop-review` repo-local. Their review, merge, and
+release-safety policies are project-specific; globally linking them could apply
+the wrong repository workflow elsewhere.
## Claude Code Compatibility
@@ -250,11 +259,20 @@ config at `.codex-plugin/mcp.json`) and `.claude-plugin/plugin.json` (Claude
Code, inline MCP config). The `skills/` folder is shared by both agents, so
keep its wording agent-neutral.
+## Cursor Compatibility
+
+Cursor reads the root `AGENTS.md` and `CLAUDE.md`; because `CLAUDE.md` is a
+symlink, both resolve to this SSOT. `.cursor/rules/openiap-ssot.mdc` is only a
+short always-applied router to the root and docs SSOT. Keep detailed project
+rules in `AGENTS.md` or `knowledge/internal/` instead of copying them into
+Cursor-specific files.
+
## Available Skills (Slash Commands / Codex Workflows)
| Skill | Description | Usage |
| -------------------- | -------------------------------------------------- | ------------------------------------- |
| `$review-self` | Review and improve current work until stable | `$review-self` or `$review-self ` |
+| `$loop-review` | Start from current main, review, PR, and merge | `$loop-review` |
| `$rebase-main` | Pull main and safely rebase the current branch | `$rebase-main` |
| `/review-pr` | Review PR comments, fix issues, resolve threads | `/review-pr 65` or `/review-pr ` |
| `/audit-code` | Audit code against knowledge rules and latest APIs | `/audit-code` |
@@ -298,4 +316,3 @@ All comprehensive rules are documented in [`knowledge/internal/`](knowledge/inte
5. **05-docs-patterns.md** - React modal patterns, component organization
6. **06-git-deployment.md** - Commit format, deployment workflows
7. **07-docs-consistency.md** - Docs/API/type consistency audits
-8. **08-gv-cloud-workspaces.md** - Safe TabTabTab `gv` cloud workspace policy
diff --git a/knowledge/README.md b/knowledge/README.md
index ec837e33c..2ccf1eaff 100644
--- a/knowledge/README.md
+++ b/knowledge/README.md
@@ -52,7 +52,6 @@ knowledge/
│ ├── 05-docs-patterns.md # React modal patterns, components
│ ├── 06-git-deployment.md # Git conventions, deployment
│ ├── 07-docs-consistency.md # Documentation SSOT audits
-│ ├── 08-gv-cloud-workspaces.md # Cloud workspace safety
│ └── sandbox-subscription-billing-issue.md
├── external/ # REFERENCE - External APIs
│ ├── amazon-iap-api.md # Amazon Appstore SDK reference
diff --git a/knowledge/_claude-context/context.md b/knowledge/_claude-context/context.md
index 3bc55ad24..d2b83c698 100644
--- a/knowledge/_claude-context/context.md
+++ b/knowledge/_claude-context/context.md
@@ -1,7 +1,7 @@
# OpenIAP Project Context
> **Auto-generated for Claude Code**
-> Last updated: 2026-08-12T17:12:21.769Z
+> Last updated: 2026-08-12T21:14:33.370Z
>
> Usage: `claude --context knowledge/_claude-context/context.md`
@@ -1540,6 +1540,27 @@ Before committing any changes:
> **Priority: MANDATORY**
> Follow these patterns when working on packages/docs.
+## Reader-First Writing Standard
+
+Apply this standard to every user-facing page, guide, API reference, migration
+note, example explanation, announcement, and release note:
+
+- Lead with the outcome, then identify who is affected and any required action.
+- Use direct, active sentences and scannable headings or bullets. Keep one idea
+ per sentence where practical.
+- State each fact once. Link to deeper reference material instead of repeating
+ the same explanation across sections or pages.
+- Omit filler, internal implementation narration, generated-file inventories,
+ test-process narration, and details that do not change user behavior.
+- Keep necessary compatibility, migration, security, data-safety, and
+ platform-specific caveats. Concision must not hide a requirement or risk.
+- Prefer concrete behavior and commands over adjectives such as "robust",
+ "comprehensive", "seamless", or "modernized."
+
+Before finishing, read the rendered page as a user. Remove any sentence that
+does not clarify what changed, how to use it, who is affected, or what action is
+required.
+
## Modal Pattern with Preact Signals
### Global Modal Management
@@ -1725,6 +1746,36 @@ Framework implementation listings must be derived from
Release notes are located at `packages/docs/src/pages/docs/updates/releases.tsx`.
+### Release Note Writing Limits
+
+Apply the project-wide Reader-First Writing Standard above. Release notes are a
+changelog for package users, not an implementation audit or a narrative of how
+a release was produced.
+
+- Lead with the user-visible outcome. Do not restate the title or begin with
+ filler such as "Publishes the coordinated release train."
+- Keep the opening summary to at most two sentences and roughly 50 words.
+- Keep each bullet to one sentence and normally 30 words or fewer. Use up to 45
+ only when a compatibility range or migration command cannot be split safely.
+- State each fact once. Do not repeat one fix in the summary, native section,
+ every wrapper bullet, and integration notes.
+- Describe behavior, compatibility, and required user action. Omit commit
+ mechanics, generated-file inventories, test matrices, release automation,
+ internal architecture, and dependency lists that do not change consumer
+ requirements.
+- A package whose only change is selecting a native dependency, regenerating
+ types, or republishing shared behavior belongs only in `Package Releases`.
+ One bullet may group packages that have the same behavior and caveats.
+- Use `Integration notes` only for required migration, configuration, or
+ compatibility action. Omit no-op reassurance and unchanged-platform lists.
+- Link a PR or issue once where it supplies useful context.
+- Prefer concrete verbs such as "fixes", "adds", "rejects", "requires",
+ "removes", and "preserves". Avoid vague verbs unless the sentence immediately
+ names the observable result.
+- Preserve historical IDs, dates, versions, links, compatibility boundaries,
+ migration commands, and shipped behavior when shortening an existing note.
+ Leave a statement unchanged when its source evidence is incomplete.
+
### Package-specific grouping for shared releases
The docs release page is the canonical release-note SSOT, including when many
@@ -2673,249 +2724,6 @@ bun run audit:docs
Exit code 1 means at least one drift; 0 means clean.
----
-
-
-
-# GV Cloud Workspace Policy
-
-> **Priority: MANDATORY**
-> Follow this policy when using TabTabTab `gv` cloud environments with OpenIAP.
-
-`gv` can be useful for OpenIAP as a safe remote maintenance runner, not as a
-release, signing, or production-credential environment. Treat every GV
-workspace as an external cloud workspace with GitHub access and no local secret
-trust by default.
-
-## Safe role for OpenIAP
-
-Use GV for secret-free OSS maintenance work:
-
-- Documentation edits, release notes, docs typecheck, and docs consistency
- audits.
-- `packages/gql` tests and schema/codegen review work that does not require
- private credentials.
-- `packages/kit` typecheck and unit tests that run without production env vars.
-- PR review response work on isolated branches/worktrees.
-- Long-running lint/test/build smoke checks that should survive local laptop
- sleep or high local resource use.
-
-Do not treat GV as the source of truth for full OpenIAP release validation.
-Native Apple signing, Play/App Store production credentials, package publishing,
-and deployment stay in the existing local or CI release systems.
-
-## Required boundaries
-
-Always keep these boundaries unless the repository owner explicitly changes this
-policy:
-
-- Onboard the repo with env capture disabled:
-
- ```bash
- gv repo add . --skip-env
- ```
-
-- First test of any new GV version or environment should be:
-
- ```bash
- gv repo add . --dry-run --skip-env
- ```
-
-- GitHub App access must be limited to the selected `hyodotdev/openiap`
- repository. Do not grant all-repository access.
-- Do not enable OpenAI/Codex auth mirroring for OpenIAP by default.
-- Do not enable local profile, CLI, shell, editor, or credential mirroring by
- default.
-- Do not add production, payment, signing, release, or deployment secrets to GV.
-- If credentials are ever needed for a GV experiment, use sandbox/test-only
- credentials with explicit owner approval.
-
-## Forbidden commands and actions
-
-Never run or recommend these for OpenIAP GV work:
-
-```bash
-gv repo add . --yes
-gv repo env list --reveal
-gv env info --reveal
-gv env info --qr
-```
-
-Also do not upload, reveal, or sync:
-
-- `.env`, `.env.local`, `.env.*`
-- App Store Connect `.p8` keys
-- Google service-account JSON files
-- signing keys, provisioning profiles, certificates, keystores, and JKS files
-- npm, NuGet, Maven Central, CocoaPods, Fly, Convex, App Store, Google Play, or
- payment provider credentials
-
-One-time GV login URLs and workspace URLs should be treated as sensitive access
-links. Do not paste them into issues, PRs, public docs, or long-lived logs.
-
-## Known GV baseline for this repo
-
-Validated on 2026-05-08 with a GV `agent-sandbox` environment:
-
-- Repo onboarding with `--skip-env` completed.
-- `gv repo env list --repo openiap --json` returned an empty env var list.
-- OpenAI auth status was disabled.
-- GitHub access was enabled only after selected-repository approval.
-- Cloud clone was clean on `main` from
- `https://github.com/hyodotdev/openiap.git`.
-- The default environment had `node`, `npm`, `corepack`, `python3`, `git`, and
- `docker`.
-- The default environment did not have `bun`, `yarn`, `java`, `swift`,
- `flutter`, or `dotnet`.
-- No `.devcontainer/devcontainer.json` existed in the repo at validation time.
-
-Because Bun is not available in the default GV environment, the safe current
-pattern is to run Bun checks inside Docker containers with the workspace mounted
-read-only.
-
-## Day-to-day usage
-
-Use GV by opening an agent or editor attached to the cloud environment, then
-give the task prompt there. The prompt is not a shell command.
-
-```bash
-gv env use agent-sandbox
-
-# Open a cloud-attached agent/editor.
-gv open opencode --env agent-sandbox
-gv open codex --env agent-sandbox
-```
-
-Use `gv ssh` for direct terminal checks in the cloud workspace:
-
-```bash
-gv ssh --env agent-sandbox
-cd ~/workspace/openiap
-git status --short --branch
-```
-
-For investigation-only work, make the boundary explicit:
-
-```text
-Investigate issue 104 and the GQL -> SDK sync flow.
-List the affected packages and propose a fix plan.
-Do not change code, commit, push, create PRs, read env files, or run deploy,
-release, signing, publish, or credential-related commands.
-```
-
-For maintenance work that may edit code, require an isolated branch and scoped
-verification:
-
-```text
-Create a branch named codex/.
-Make the smallest safe change for the requested docs/GQL/kit issue.
-Do not touch env, signing, release, deploy, or publish files.
-Run only the relevant secret-free checks, then summarize the diff and results.
-```
-
-## Safe verification pattern
-
-Prefer an ephemeral Docker container with a read-only repo mount and an internal
-copy:
-
-```bash
-gv ssh --env agent-sandbox -- \
- 'set -eu
- OPENIAP_PATH="${OPENIAP_PATH:-$HOME/workspace/openiap}"
- test -d "$OPENIAP_PATH"
- docker run --rm \
- -v "$OPENIAP_PATH:/src:ro" \
- -w /work \
- oven/bun:1.3.13 \
- bash -lc "cp -a /src/. /work && bun install --frozen-lockfile && bun run audit:docs"'
-```
-
-Why this pattern:
-
-- `:ro` prevents the container from writing to the GV checkout.
-- `/work` is a temporary container copy, so `node_modules`, build output, and
- generated files disappear when the container exits.
-- It avoids syncing local env files or local uncommitted changes.
-
-After any GV run, verify both workspace cleanliness and env state:
-
-```bash
-gv ssh --env agent-sandbox -- \
- 'cd ~/workspace/openiap && git status --short --branch'
-
-gv repo env list --repo openiap --json
-```
-
-## Verified safe smoke checks
-
-These checks have run successfully inside the Docker `/work` copy in the
-GV read-only pattern, not directly in the default GV host shell. Bun is not
-available in the default GV environment unless a future setup script installs
-it.
-
-```bash
-# GQL tests
-cd packages/gql && bun run test
-
-# Docs typecheck
-cd packages/docs && bun run typecheck
-
-# Kit typecheck and tests
-cd packages/kit && bun run typecheck && bun run test
-
-# Docs consistency audit
-bun run audit:docs
-```
-
-Use these as the first GV regression suite for docs, GQL, and IAPKit
-maintenance work.
-
-## Out of scope for GV until explicitly proven
-
-Do not use GV as the default runner for:
-
-- `packages/apple` SwiftPM/Xcode signing or release workflows.
-- iOS/macOS Godot, Expo, React Native, KMP, Flutter, or MAUI device builds.
-- Android/KMP release publishing that needs Maven Central signing credentials.
-- Flutter pub.dev, npm, NuGet, CocoaPods trunk, GitHub release, or deployment
- publishing.
-- Fly/Convex production deploys.
-- Any flow that requires production IAP, payment, App Store Connect, Google
- Play, or signing credentials.
-
-Linux-friendly Android/KMP checks may become reasonable after the repository has
-a minimal GV/devcontainer setup with Java installed, but production credentials
-still remain out of scope.
-
-## Branch and PR workflow
-
-Use GV for isolated work, not direct `main` edits:
-
-1. Start from the clean cloud clone.
-2. Create a branch such as `codex/docs-gv-audit` or `codex/kit-gv-smoke`.
-3. Run only secret-free checks.
-4. Review `git diff` and `git status`.
-5. Push only intentional source changes.
-6. Open a PR for normal CI review.
-
-Do not push release, signing, or deployment changes from GV without explicit
-owner approval.
-
-## Future improvement
-
-If GV becomes part of regular maintenance, add a minimal devcontainer or setup
-script for the Linux-friendly subset:
-
-- Bun pinned to the root `packageManager`.
-- Node/Corepack.
-- Java for Gradle checks.
-- Optional Android command-line tooling if needed.
-
-Do not add Swift, Xcode, Flutter, .NET, signing tools, or production secret
-setup to the first GV devcontainer. Keep the first iteration small and focused
-on docs, GQL, kit, and non-release Android/KMP smoke checks.
-
-
---
diff --git a/knowledge/internal/05-docs-patterns.md b/knowledge/internal/05-docs-patterns.md
index 2dd920353..8f780a667 100644
--- a/knowledge/internal/05-docs-patterns.md
+++ b/knowledge/internal/05-docs-patterns.md
@@ -3,6 +3,27 @@
> **Priority: MANDATORY**
> Follow these patterns when working on packages/docs.
+## Reader-First Writing Standard
+
+Apply this standard to every user-facing page, guide, API reference, migration
+note, example explanation, announcement, and release note:
+
+- Lead with the outcome, then identify who is affected and any required action.
+- Use direct, active sentences and scannable headings or bullets. Keep one idea
+ per sentence where practical.
+- State each fact once. Link to deeper reference material instead of repeating
+ the same explanation across sections or pages.
+- Omit filler, internal implementation narration, generated-file inventories,
+ test-process narration, and details that do not change user behavior.
+- Keep necessary compatibility, migration, security, data-safety, and
+ platform-specific caveats. Concision must not hide a requirement or risk.
+- Prefer concrete behavior and commands over adjectives such as "robust",
+ "comprehensive", "seamless", or "modernized."
+
+Before finishing, read the rendered page as a user. Remove any sentence that
+does not clarify what changed, how to use it, who is affected, or what action is
+required.
+
## Modal Pattern with Preact Signals
### Global Modal Management
@@ -188,6 +209,36 @@ Framework implementation listings must be derived from
Release notes are located at `packages/docs/src/pages/docs/updates/releases.tsx`.
+### Release Note Writing Limits
+
+Apply the project-wide Reader-First Writing Standard above. Release notes are a
+changelog for package users, not an implementation audit or a narrative of how
+a release was produced.
+
+- Lead with the user-visible outcome. Do not restate the title or begin with
+ filler such as "Publishes the coordinated release train."
+- Keep the opening summary to at most two sentences and roughly 50 words.
+- Keep each bullet to one sentence and normally 30 words or fewer. Use up to 45
+ only when a compatibility range or migration command cannot be split safely.
+- State each fact once. Do not repeat one fix in the summary, native section,
+ every wrapper bullet, and integration notes.
+- Describe behavior, compatibility, and required user action. Omit commit
+ mechanics, generated-file inventories, test matrices, release automation,
+ internal architecture, and dependency lists that do not change consumer
+ requirements.
+- A package whose only change is selecting a native dependency, regenerating
+ types, or republishing shared behavior belongs only in `Package Releases`.
+ One bullet may group packages that have the same behavior and caveats.
+- Use `Integration notes` only for required migration, configuration, or
+ compatibility action. Omit no-op reassurance and unchanged-platform lists.
+- Link a PR or issue once where it supplies useful context.
+- Prefer concrete verbs such as "fixes", "adds", "rejects", "requires",
+ "removes", and "preserves". Avoid vague verbs unless the sentence immediately
+ names the observable result.
+- Preserve historical IDs, dates, versions, links, compatibility boundaries,
+ migration commands, and shipped behavior when shortening an existing note.
+ Leave a statement unchanged when its source evidence is incomplete.
+
### Package-specific grouping for shared releases
The docs release page is the canonical release-note SSOT, including when many
diff --git a/knowledge/internal/08-gv-cloud-workspaces.md b/knowledge/internal/08-gv-cloud-workspaces.md
deleted file mode 100644
index af62aeed3..000000000
--- a/knowledge/internal/08-gv-cloud-workspaces.md
+++ /dev/null
@@ -1,237 +0,0 @@
-# GV Cloud Workspace Policy
-
-> **Priority: MANDATORY**
-> Follow this policy when using TabTabTab `gv` cloud environments with OpenIAP.
-
-`gv` can be useful for OpenIAP as a safe remote maintenance runner, not as a
-release, signing, or production-credential environment. Treat every GV
-workspace as an external cloud workspace with GitHub access and no local secret
-trust by default.
-
-## Safe role for OpenIAP
-
-Use GV for secret-free OSS maintenance work:
-
-- Documentation edits, release notes, docs typecheck, and docs consistency
- audits.
-- `packages/gql` tests and schema/codegen review work that does not require
- private credentials.
-- `packages/kit` typecheck and unit tests that run without production env vars.
-- PR review response work on isolated branches/worktrees.
-- Long-running lint/test/build smoke checks that should survive local laptop
- sleep or high local resource use.
-
-Do not treat GV as the source of truth for full OpenIAP release validation.
-Native Apple signing, Play/App Store production credentials, package publishing,
-and deployment stay in the existing local or CI release systems.
-
-## Required boundaries
-
-Always keep these boundaries unless the repository owner explicitly changes this
-policy:
-
-- Onboard the repo with env capture disabled:
-
- ```bash
- gv repo add . --skip-env
- ```
-
-- First test of any new GV version or environment should be:
-
- ```bash
- gv repo add . --dry-run --skip-env
- ```
-
-- GitHub App access must be limited to the selected `hyodotdev/openiap`
- repository. Do not grant all-repository access.
-- Do not enable OpenAI/Codex auth mirroring for OpenIAP by default.
-- Do not enable local profile, CLI, shell, editor, or credential mirroring by
- default.
-- Do not add production, payment, signing, release, or deployment secrets to GV.
-- If credentials are ever needed for a GV experiment, use sandbox/test-only
- credentials with explicit owner approval.
-
-## Forbidden commands and actions
-
-Never run or recommend these for OpenIAP GV work:
-
-```bash
-gv repo add . --yes
-gv repo env list --reveal
-gv env info --reveal
-gv env info --qr
-```
-
-Also do not upload, reveal, or sync:
-
-- `.env`, `.env.local`, `.env.*`
-- App Store Connect `.p8` keys
-- Google service-account JSON files
-- signing keys, provisioning profiles, certificates, keystores, and JKS files
-- npm, NuGet, Maven Central, CocoaPods, Fly, Convex, App Store, Google Play, or
- payment provider credentials
-
-One-time GV login URLs and workspace URLs should be treated as sensitive access
-links. Do not paste them into issues, PRs, public docs, or long-lived logs.
-
-## Known GV baseline for this repo
-
-Validated on 2026-05-08 with a GV `agent-sandbox` environment:
-
-- Repo onboarding with `--skip-env` completed.
-- `gv repo env list --repo openiap --json` returned an empty env var list.
-- OpenAI auth status was disabled.
-- GitHub access was enabled only after selected-repository approval.
-- Cloud clone was clean on `main` from
- `https://github.com/hyodotdev/openiap.git`.
-- The default environment had `node`, `npm`, `corepack`, `python3`, `git`, and
- `docker`.
-- The default environment did not have `bun`, `yarn`, `java`, `swift`,
- `flutter`, or `dotnet`.
-- No `.devcontainer/devcontainer.json` existed in the repo at validation time.
-
-Because Bun is not available in the default GV environment, the safe current
-pattern is to run Bun checks inside Docker containers with the workspace mounted
-read-only.
-
-## Day-to-day usage
-
-Use GV by opening an agent or editor attached to the cloud environment, then
-give the task prompt there. The prompt is not a shell command.
-
-```bash
-gv env use agent-sandbox
-
-# Open a cloud-attached agent/editor.
-gv open opencode --env agent-sandbox
-gv open codex --env agent-sandbox
-```
-
-Use `gv ssh` for direct terminal checks in the cloud workspace:
-
-```bash
-gv ssh --env agent-sandbox
-cd ~/workspace/openiap
-git status --short --branch
-```
-
-For investigation-only work, make the boundary explicit:
-
-```text
-Investigate issue 104 and the GQL -> SDK sync flow.
-List the affected packages and propose a fix plan.
-Do not change code, commit, push, create PRs, read env files, or run deploy,
-release, signing, publish, or credential-related commands.
-```
-
-For maintenance work that may edit code, require an isolated branch and scoped
-verification:
-
-```text
-Create a branch named codex/.
-Make the smallest safe change for the requested docs/GQL/kit issue.
-Do not touch env, signing, release, deploy, or publish files.
-Run only the relevant secret-free checks, then summarize the diff and results.
-```
-
-## Safe verification pattern
-
-Prefer an ephemeral Docker container with a read-only repo mount and an internal
-copy:
-
-```bash
-gv ssh --env agent-sandbox -- \
- 'set -eu
- OPENIAP_PATH="${OPENIAP_PATH:-$HOME/workspace/openiap}"
- test -d "$OPENIAP_PATH"
- docker run --rm \
- -v "$OPENIAP_PATH:/src:ro" \
- -w /work \
- oven/bun:1.3.13 \
- bash -lc "cp -a /src/. /work && bun install --frozen-lockfile && bun run audit:docs"'
-```
-
-Why this pattern:
-
-- `:ro` prevents the container from writing to the GV checkout.
-- `/work` is a temporary container copy, so `node_modules`, build output, and
- generated files disappear when the container exits.
-- It avoids syncing local env files or local uncommitted changes.
-
-After any GV run, verify both workspace cleanliness and env state:
-
-```bash
-gv ssh --env agent-sandbox -- \
- 'cd ~/workspace/openiap && git status --short --branch'
-
-gv repo env list --repo openiap --json
-```
-
-## Verified safe smoke checks
-
-These checks have run successfully inside the Docker `/work` copy in the
-GV read-only pattern, not directly in the default GV host shell. Bun is not
-available in the default GV environment unless a future setup script installs
-it.
-
-```bash
-# GQL tests
-cd packages/gql && bun run test
-
-# Docs typecheck
-cd packages/docs && bun run typecheck
-
-# Kit typecheck and tests
-cd packages/kit && bun run typecheck && bun run test
-
-# Docs consistency audit
-bun run audit:docs
-```
-
-Use these as the first GV regression suite for docs, GQL, and IAPKit
-maintenance work.
-
-## Out of scope for GV until explicitly proven
-
-Do not use GV as the default runner for:
-
-- `packages/apple` SwiftPM/Xcode signing or release workflows.
-- iOS/macOS Godot, Expo, React Native, KMP, Flutter, or MAUI device builds.
-- Android/KMP release publishing that needs Maven Central signing credentials.
-- Flutter pub.dev, npm, NuGet, CocoaPods trunk, GitHub release, or deployment
- publishing.
-- Fly/Convex production deploys.
-- Any flow that requires production IAP, payment, App Store Connect, Google
- Play, or signing credentials.
-
-Linux-friendly Android/KMP checks may become reasonable after the repository has
-a minimal GV/devcontainer setup with Java installed, but production credentials
-still remain out of scope.
-
-## Branch and PR workflow
-
-Use GV for isolated work, not direct `main` edits:
-
-1. Start from the clean cloud clone.
-2. Create a branch such as `codex/docs-gv-audit` or `codex/kit-gv-smoke`.
-3. Run only secret-free checks.
-4. Review `git diff` and `git status`.
-5. Push only intentional source changes.
-6. Open a PR for normal CI review.
-
-Do not push release, signing, or deployment changes from GV without explicit
-owner approval.
-
-## Future improvement
-
-If GV becomes part of regular maintenance, add a minimal devcontainer or setup
-script for the Linux-friendly subset:
-
-- Bun pinned to the root `packageManager`.
-- Node/Corepack.
-- Java for Gradle checks.
-- Optional Android command-line tooling if needed.
-
-Do not add Swift, Xcode, Flutter, .NET, signing tools, or production secret
-setup to the first GV devcontainer. Keep the first iteration small and focused
-on docs, GQL, kit, and non-release Android/KMP smoke checks.
diff --git a/packages/docs/src/components/EcosystemDiagram.tsx b/packages/docs/src/components/EcosystemDiagram.tsx
index 5a566ae04..fb0870c39 100644
--- a/packages/docs/src/components/EcosystemDiagram.tsx
+++ b/packages/docs/src/components/EcosystemDiagram.tsx
@@ -245,28 +245,76 @@ function EcosystemDiagram() {
const mark = FRAMEWORK_MARKS[lib.name] ?? lib.image;
return (
-
-
-
- {lib.displayName}
- {lib.description}
-
-
- {lib.version}
+
diff --git a/packages/docs/src/pages/docs/updates/releases.tsx b/packages/docs/src/pages/docs/updates/releases.tsx
index 70b1d2272..03e67510a 100644
--- a/packages/docs/src/pages/docs/updates/releases.tsx
+++ b/packages/docs/src/pages/docs/updates/releases.tsx
@@ -236,7 +236,9 @@ function Releases() {
color: 'var(--text-secondary)',
}}
>
- Publishes the store-verification integrity release from{' '}
+ Amazon verification now checks product identity and returns sandbox
+ or production provenance across every SDK. Horizon now keeps the
+ last confirmed purchase state when verification is ambiguous (
PR #313
- . The release makes Amazon sandbox provenance and product binding
- first-class across every SDK, removes the unfinished Horizon
- subscription lane, and keeps transient store failures from replacing
- the last authoritative purchase state.
+ ).
Common changes
@@ -259,13 +258,9 @@ function Releases() {
}}
>
- Hosted IAPKit now requires an explicit project opt-in for Amazon
- App Tester and RVS Cloud Sandbox, records Sandbox or{' '}
- Production provenance, and supports caller-provided{' '}
- expectedProductId binding. A bounded receipt
- reconciler refreshes active Amazon purchase rows without
- overwriting authoritative state on timeout, throttling, secret,
- network, or malformed-response failures, resolving{' '}
+ Hosted IAPKit requires explicit Amazon sandbox opt-in, records the
+ verification environment, checks expectedProductId,
+ and preserves authoritative state on non-authoritative failures (
issue #311
- .
+ ).
- Horizon verification is now a conservative synchronous REST path:
- only strict boolean ownership verdicts are persisted, retryable or
- ambiguous responses leave the last confirmed snapshot untouched,
- and the structurally unsafe background subscription reconciler and
- its synthetic revenue events are retired. This resolves{' '}
+ Horizon persists only explicit ownership results; ambiguous
+ responses keep the last snapshot, and the background subscription
+ reconciler and synthetic revenue events are removed (
issue #310
- .
+ ).
- Purchase analytics add Amazon and Horizon store counters. The
- project shell, tabs, filters, tables, metric cards, and long
- project identities now keep horizontal scrolling local and remain
- usable with an expanded sidebar at tablet and desktop widths.
+ Purchase analytics include Amazon and Horizon, and wide dashboard
+ content now scrolls inside its own container.
@@ -309,22 +300,15 @@ function Releases() {
}}
>
- OpenIAP Spec 3.2.0 - adds optional Amazon{' '}
+ OpenIAP Spec 3.2.0 - adds optional{' '}
expectedProductId input and optional verification{' '}
- environment output while keeping existing request and
- result constructors source-compatible.
-
-
- openiap-apple 3.2.0 - forwards the Amazon product
- guard and preserves a validated Sandbox or{' '}
- Production result through the provider verification
- bridge.
+ environment output without breaking existing
+ constructors.
- openiap-google 3.3.0 - carries the same input and
- provenance through Play, Amazon, and Horizon builds, including the
- Fire OS path that obtains a missing Amazon user ID before
- verification.
+ openiap-apple 3.2.0 and{' '}
+ openiap-google 3.3.0 forward both fields; Fire OS
+ also fetches a missing Amazon user ID before verification.
@@ -337,37 +321,14 @@ function Releases() {
}}
>
- react-native-iap 16.3.0 - exposes Amazon product
- binding and environment provenance through Nitro, native, and Vega
- paths. When verification is enabled, the example uses explicit
- sandbox configuration and finishes a purchase only after
+ react-native-iap 16.3.0 - forwards Amazon product
+ binding and provenance; its example finishes purchases only after
verification succeeds.
- expo-iap 5.3.0 - preserves the new fields across
- Expo Modules and Vega, and serializes restored or overlapping
- purchase callbacks so remounts and reconnects cannot verify or
- finish the same receipt twice.
-
-
- flutter_inapp_purchase 10.3.0 - forwards the
- exact Amazon product identifier through Dart and every native
- channel, then validates and returns the optional environment.
-
-
- godot-iap 3.3.0 - ships the generated Amazon
- input and environment result contract in the GDScript plugin and
- updated Android and iOS release artifacts.
-
-
- kmp-iap 3.3.0 - maps the new fields through the
- Android and iOS bridges and publishes matching Play, Amazon,
- Horizon, and Apple variants.
-
-
- OpenIap.Maui 2.3.0 - adds the generated C#
- contract and uses the requested product ID in the Amazon example
- while preserving the environment in verification results.
+ expo-iap 5.3.0 - serializes overlapping purchase
+ callbacks so remounts and reconnects cannot verify or finish one
+ receipt twice.
@@ -382,24 +343,23 @@ function Releases() {
Enable{' '}
Allow Amazon App Tester / RVS Cloud Sandbox in
- the IAPKit project before sending sandbox: true.
- Production verification still requires the project's Amazon RVS
- shared secret. Check both the verified product ID and expected
- environment before granting or finishing a purchase.
+ IAPKit before sending sandbox: true; production still
+ requires the Amazon RVS shared secret.
+
+
+ Grant access only when the verified product ID and environment
+ match the request.
- Amazon reconciliation updates purchase rows only. It uses{' '}
- cancelDate as Amazon's loss-of-access signal and does
- not create subscription rows or infer expiry from a past{' '}
- renewalDate. Horizon likewise remains raw ownership
- verification without background subscription lifecycle state.
+ Amazon uses cancelDate for lost access, creates no
+ subscription rows, and infers no expiry from{' '}
+ renewalDate; Horizon remains ownership-only.
Self-hosted IAPKit deployments with historical Amazon or Horizon
purchases should run{' '}
migrations:backfillPurchaseStatsStoreBuckets after
- the base purchase-stats backfill. The hosted audit found no
- historical rows that required this migration.
+ the base purchase-stats backfill.
@@ -456,7 +416,8 @@ function Releases() {
color: 'var(--text-secondary)',
}}
>
- Publishes the Android subscription replacement reliability fix from{' '}
+ Google Play subscription upgrades and downgrades now survive R8
+ minification by using typed Billing 9.1 replacement parameters (
PR #309
- . Minified Google Play release builds now construct product-level
- replacement parameters through typed Play Billing 9.1 APIs instead
- of class- and method-name reflection.
+ ).
@@ -480,11 +439,9 @@ function Releases() {
}}
>
- openiap-google 3.2.3 - replaces reflective
- construction of subscription product replacement parameters with
- typed Play Billing 9.1 calls, so R8 can safely rewrite the
- references without an OpenIAP-specific broad Billing keep rule.
- All seven replacement modes retain their native values, resolving{' '}
+ openiap-google 3.2.3 - replaces reflection with
+ typed Billing calls while preserving all seven replacement modes,
+ resolving{' '}
-
- Promoted-product examples now refetch mixed product details and
- select the subscription request branch when the promoted item is a
- subscription. The Advanced Commerce period field also carries its
- precise OpenIAP and Apple availability in every generated SDK.
+ Promoted-product examples now select the correct product type, and
+ Advanced Commerce period docs identify their exact availability.
@@ -648,26 +555,15 @@ function Releases() {
}}
>
- OpenIAP Spec 3.1.1 - synchronizes the Advanced
- Commerce period availability clarification used by every generated
- SDK.
+ openiap-apple 3.1.1 - reserves a redeemed
+ win-back offer for one matching promoted purchase and safely
+ releases it after failure without letting a stale attempt replace
+ a newer purchase intent.
- openiap-apple 3.1.1 - exclusively reserves an
- externally redeemed win-back offer for one matching promoted
- purchase attempt. Local validation and presentation failures
- release the reservation for a safe retry, while newer purchase
- intents cannot be overwritten by a stale attempt.
-
-
- openiap-google 3.2.2 - makes native convenience
- Activity binding lifecycle-aware and owner-scoped. A paused or
- disposed Compose owner no longer clears another active owner, and
- Horizon ViewModel callers have an explicit Activity-based
- initialization path. It also restores Kotlin 2.1.20+ consumer
- compatibility by publishing Kotlin 2.2.0 metadata and validating
- Play, Horizon, and Amazon from an independent Kotlin 2.1.20
- consumer before publication ({' '}
+ openiap-google 3.2.2 - prevents one Compose owner
+ from clearing another owner's Activity and restores Kotlin
+ 2.1.20+ compatibility (
-
- openiap-apple 3.1.0 captures externally redeemed
- win-back offers for matching promoted purchases, selects the
- newest verified current entitlement deterministically, and returns
- a verified redemption purchase on Apple 27+ when built with Xcode
- 27+. Older supported system-sheet paths continue to return{' '}
- null after presentation.
+ openiap-apple 3.1.0 - matches redeemed win-back
+ offers to promoted purchases, selects the newest verified current
+ entitlement, and returns a verified redemption purchase on Apple
+ 27+ with Xcode 27+.
- openiap-google 3.2.0 requests suspended
- subscriptions only when the connected Play Store supports that
- capability, otherwise falling back to active purchases. Horizon
- initialization now requires a foreground Activity,
- and Horizon purchase requests reject multi-product payloads before
- invoking the store.
+ openiap-google 3.2.0 - fetches suspended Play
+ subscriptions only when supported; Horizon requires a foreground{' '}
+ Activity and one product per purchase request.
- Advanced Commerce purchase metadata now carries its optional{' '}
- period across the shared schema and generated Apple,
- TypeScript, Dart, GDScript, Kotlin, and C# models.
+ OpenIAP Spec 3.1.0 - adds optional Advanced
+ Commerce period metadata to every generated SDK.
@@ -849,23 +704,12 @@ function Releases() {
}}
>
- react-native-iap 16.2.0 and{' '}
- expo-iap 5.2.0 expose the synchronized Apple
- period metadata and updated promoted-product, redemption, and
- Horizon contracts. Expo prebuilds also isolate the local OpenIAP
- composite-build output from other Android consumers.
-
-
- flutter_inapp_purchase 10.2.0,{' '}
- godot-iap 3.2.0, and{' '}
- OpenIap.Maui 2.2.0 publish the synchronized Apple
- purchase metadata and corrected redemption guidance for their
- generated types, wrappers, tests, and examples.
+ expo-iap 5.2.0 - isolates local OpenIAP composite
+ build output so it cannot affect other Android consumers.
- kmp-iap 3.2.0 adds the same Apple metadata while
- applying the Play suspended-subscription capability fallback to
- its Android restore path.
+ kmp-iap 3.2.0 - applies the Play suspended-
+ subscription capability fallback to Android restore.
- No public API call signature was removed. Upgrade through each
- SDK's normal package manager to pick up the store-safety fixes.
-
Start Horizon billing only while the app has a foreground Android
- activity, and submit exactly one product in each Horizon purchase
+ Activity, and submit exactly one product in each Horizon purchase
request.
- Treat a null offer-code redemption result as a
- successfully presented system sheet on supported older paths, then
- refresh purchases or entitlements after the customer completes
- redemption.
+ On older Apple paths, null means the redemption sheet
+ was presented; refresh purchases after the customer finishes.
@@ -947,7 +785,9 @@ function Releases() {
color: 'var(--text-secondary)',
}}
>
- Publishes the coordinated minor release train from{' '}
+ Updates supported build toolchains while preserving host compiler
+ compatibility. React Native and Expo also fix stale{' '}
+ useIAP initialization (
PR #294
- {' '}
- across the Android native package and every framework library. The
- train moves each maintained build to current supported dependencies,
- migrates APIs and configuration deprecated by those upgrades, and
- preserves the consumer compatibility bounds validated across Google
- Play, Amazon Appstore, Meta Horizon Store, and Apple platforms.
+
+ ).
-
Common changes
-
-
- Standalone Android builds move to Kotlin 2.4.10, Gradle 9.3.0,
- Android SDK 36, Kotlin Coroutines 1.11.0, and Gson 2.14.0. Host
- integrations still use the compiler selected by React Native,
- Expo, or Flutter instead of forcing the standalone Kotlin line
- into an incompatible consumer build.
-
-
- Obsolete AndroidX KTX coordinates are replaced by the merged base
- artifacts, while compatibility caps remain explicit where newer
- AndroidX releases require API 37 / AGP 9.1 or newer Kotlin
- metadata than a supported host can read.
-
-
- Deprecated lint, test, native-registration, Kotlin, publishing,
- and MAUI dialog APIs are migrated to their supported replacements.
- Release artifacts are also bound to immutable source tags, with
- npm packages publishing verified Sigstore provenance.
-
-
-
Shared spec and native packages
@@ -1003,13 +810,10 @@ function Releases() {
}}
>
- openiap-google 3.1.0 - modernizes the Play,
- Amazon, and Horizon artifacts together, including Kotlin 2.4.10,
- Coroutines 1.11.0, Gson 2.14.0, AndroidX base artifacts, and the
- typed Vanniktech publishing API. AndroidX Core 1.18.0 and
- Lifecycle 2.10.0 retain the API 36 / AGP 8.13 consumer line, and
- Horizon serialization stays on 1.9.0 for Expo SDK 57 Kotlin
- metadata compatibility.
+ openiap-google 3.1.0 - moves standalone builds to
+ Kotlin 2.4.10, Gradle 9.3.0, and SDK 36, keeps AndroidX Core
+ 1.18.0 and Lifecycle 2.10.0 on the API 36 / AGP 8.13 consumer
+ line, and holds Horizon serialization at 1.9.0 for Expo SDK 57.
@@ -1022,47 +826,32 @@ function Releases() {
}}
>
- react-native-iap 16.1.0 - updates the validated
- React 19 / React Native 0.86 / Nitro 0.36.5 toolchain, adopts the
- current BaseReactPackage and fbjni registration APIs,
- and prevents a superseded or unmounted useIAP{' '}
- initialization from installing listeners or updating state.
+ react-native-iap 16.1.0 - validates React 19,
+ React Native 0.86, and Nitro 0.36.5, and prevents stale{' '}
+ useIAP initialization from installing listeners.
- expo-iap 5.1.0 - validates Expo SDK 57 and its
- React Native 0.86 stack, keeps local Android builds on Expo's
- compatible Kotlin 2.1.20 compiler, replaces deprecated Android and
- Babel dependencies, and closes the corresponding{' '}
- useIAP initialization and teardown race.
+ expo-iap 5.1.0 - validates Expo SDK 57 with
+ Kotlin 2.1.20 and fixes the same useIAP{' '}
+ initialization race.
- flutter_inapp_purchase 10.1.0 - supports both
- Flutter's transitional Kotlin plugin path and AGP 9 built-in
- Kotlin, moves the Android build to SDK 36 and Coroutines 1.11.0,
- and migrates the example to the current Flutter lints and
- flutter_dotenv APIs.
+ flutter_inapp_purchase 10.1.0 - supports both the
+ transitional Kotlin plugin and AGP 9 built-in Kotlin on SDK 36.
- godot-iap 3.1.0 - refreshes the precompiled
- Android and Apple artifacts with Godot 4.7.1, SwiftGodot 0.79.0,
- Kotlin 2.4.10, Gradle 9.3.0, and Coroutines 1.11.0 while retaining
- Godot 4.3+ compatibility for the released addon.
+ godot-iap 3.1.0 - refreshes precompiled artifacts
+ with Godot 4.7.1 and SwiftGodot 0.79.0 while retaining Godot 4.3+
+ runtime compatibility.
- kmp-iap 3.1.0 - moves the Android/iOS library to
- Kotlin 2.4.10, Gradle 9.3.0, Compose Multiplatform 1.10.3, Dokka
- 2.2.0, Coroutines 1.11.0, Serialization 1.11.0, and the current
- typed Maven publishing API. Compose remains capped at 1.10.3 for
- iosX64 compatibility, and Material Icons remains at 1.7.3 because
- no newer compatible artifact is published.
+ kmp-iap 3.1.0 - moves to Kotlin 2.4.10, Gradle
+ 9.3.0, and Compose 1.10.3; Compose remains capped for iosX64.
- OpenIap.Maui 2.1.0 - aligns the NuGet dependency
- graph with .NET 10 MAUI 10.0.90 and the updated Android bindings,
- while its example replaces deprecated dialog methods, routes Apple
- JWS, Google tokens, and Amazon receipt identity to custom or local
- IAPKit endpoints, and leaves transactions unfinished when
- verification fails.
+ OpenIap.Maui 2.1.0 - supports .NET 10 MAUI
+ 10.0.90; its example sends store receipts to IAPKit and leaves
+ failed verifications unfinished.
@@ -1075,20 +864,14 @@ function Releases() {
}}
>
- No OpenIAP API migration is required; upgrade to the package
- versions below through the normal package manager for each SDK.
-
-
- React Native projects require React Native 0.79+ and Node.js 18+.
- Expo projects should follow their SDK's Kotlin, Node.js, Android,
- and iOS baselines; SDK 57 is the validated current setup, while
- SDK 52 is no longer compatible with the Android artifacts.
+ React Native projects require React Native 0.79+ and Node.js 18+;
+ Expo SDK 57 is validated, while SDK 52 is incompatible with these
+ Android artifacts.
- The released Godot addon supports Godot 4.3+, while source builds
- now require Godot 4.7.1, SwiftGodot 0.79.0, Swift 6.3, and Xcode
- 26.5+. KMP builds require Kotlin 2.4.10, Gradle 9.3.0, and JDK
- 17+.
+ Godot source builds require Godot 4.7.1, SwiftGodot 0.79.0, Swift
+ 6.3, and Xcode 26.5+; KMP builds require Kotlin 2.4.10, Gradle
+ 9.3.0, and JDK 17+.