{"id":51941323,"url":"https://github.com/alisabry22/storeops","last_synced_at":"2026-07-28T19:01:27.926Z","repository":{"id":372801848,"uuid":"1294965828","full_name":"alisabry22/storeops","owner":"alisabry22","description":"Open-source control room for verified App Store Connect and Google Play operations.","archived":false,"fork":false,"pushed_at":"2026-07-23T12:51:51.000Z","size":80609,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-23T14:12:01.360Z","etag":null,"topics":["app-store-connect","google-play","nextjs","pricing","release-automation","self-hosted","typescript"],"latest_commit_sha":null,"homepage":"https://www.storeops.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alisabry22.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":"GOVERNANCE.md","roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-07-09T09:11:51.000Z","updated_at":"2026-07-23T12:49:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/alisabry22/storeops","commit_stats":null,"previous_names":["alisabry22/storeops"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/alisabry22/storeops","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisabry22%2Fstoreops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisabry22%2Fstoreops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisabry22%2Fstoreops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisabry22%2Fstoreops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alisabry22","download_url":"https://codeload.github.com/alisabry22/storeops/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alisabry22%2Fstoreops/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36003882,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-28T02:00:06.341Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app-store-connect","google-play","nextjs","pricing","release-automation","self-hosted","typescript"],"created_at":"2026-07-28T19:01:26.892Z","updated_at":"2026-07-28T19:01:27.915Z","avatar_url":"https://github.com/alisabry22.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# StoreOps\n\n**Open-source operations for App Store Connect and Google Play.**\n\n[![CI](https://github.com/alisabry22/storeops/actions/workflows/ci.yml/badge.svg)](https://github.com/alisabry22/storeops/actions/workflows/ci.yml)\n[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)](LICENSE)\n[![StoreOps Cloud](https://img.shields.io/badge/cloud-storeops.dev-10b981)](https://www.storeops.dev)\n\nStoreOps gives shipping teams one place to preview, apply, verify, and recover\nregional pricing and release metadata without repeating the same operation in\nhundreds of storefronts.\n\nIt is available in two forms:\n\n- **StoreOps Community:** free, self-hosted, and developer-controlled.\n- **StoreOps Cloud:** the hosted service with account-backed synchronization,\n  managed upgrades, billing, and maintainer support.\n\nThe core store-operation features are available in the Community Edition. Cloud\nrevenue funds maintenance and continued open-source development.\n\n## What it does\n\n- Connects App Store Connect and Google Play using developer-provided keys.\n- Loads subscriptions, in-app products, and regional prices.\n- Builds deterministic worldwide pricing previews from official store data.\n- Enforces a maximum movement cap immediately before a pricing write.\n- Saves a complete pricing snapshot before applying.\n- Re-reads the store after a write and reports success only when values match.\n- Edits localized App Store and Google Play listing metadata.\n- Prepares localized Google Play “What’s new” notes in Play Console format.\n- Imports and exports auditable CSV price sheets.\n\nAI is optional and limited to selecting a pricing strategy and movement cap. It\nnever generates the final production territory price grid.\n\n## Run Community Edition\n\n### Docker\n\n```bash\ngit clone https://github.com/alisabry22/storeops.git\ncd storeops\ndocker compose up --build -d\n```\n\nOpen [http://localhost:3000](http://localhost:3000).\n\n### Node.js\n\nNode.js 22 or newer is required.\n\n```bash\ngit clone https://github.com/alisabry22/storeops.git\ncd storeops\nnpm ci\ncp community.env.example .env.local\nnpm run dev\n```\n\nCommunity mode needs no Clerk project, database, or Lemon Squeezy account. See\n[the self-hosting guide](docs/SELF_HOSTING.md) before exposing it publicly.\n\n## Safety model\n\nEvery high-impact workflow follows the same contract:\n\n1. Read the current store state.\n2. Build a current-versus-proposed preview.\n3. Enforce deterministic policy and movement limits.\n4. Save a complete browser recovery point before pricing mutations.\n5. Apply only after explicit confirmation.\n6. Read the store again and verify the accepted values.\n\nApple `.p8` and Google service-account keys are imported as non-extractable\nWebCrypto keys in IndexedDB. Raw private-key material is not intentionally\nuploaded. Short-lived store tokens traverse a narrow same-origin proxy because\nthe store APIs block browser CORS.\n\n“Non-extractable” does not protect against malicious code already executing in\nthe page. Community operators must protect the host, dependency chain, browser,\nTLS termination, and request logs. Use revocable, least-privilege store roles.\n\n## Store behavior\n\n- **Apple:** targets snap to official price points. Subscription preservation is\n  requested only for eligible increases. Corrective changes follow the\n  schedules Apple permits; completed billing is not reversible.\n- **Google Play:** current storefront grids can be restored from retained\n  snapshots. Subscription legacy cohorts remain separate from pricing for new\n  purchasers. Metadata writes use a fresh Edit, validation, protected commit,\n  and post-commit verification.\n\n### Provider terms\n\nStoreOps is independent software and is not endorsed by Apple or Google.\nOperators are responsible for their agreements, permissions, review rules, and\nAPI use. Google’s\n[Developer API usage instructions](https://developers.google.com/android-publisher/api_usage)\ninclude restrictions on third-party publishing services and credential sharing.\nSelf-hosting does not waive those terms or constitute Google approval.\n\n## Community and Cloud configuration\n\n`NEXT_PUBLIC_STOREOPS_EDITION` is a build-time value:\n\n| Value | Behavior |\n| --- | --- |\n| `community` | Core writes unlocked; no account, billing, or database required |\n| unset / `cloud` | Clerk accounts and server-verified paid write entitlement |\n\nDo not enable Community mode in the hosted StoreOps Cloud deployment. Public\nNext.js variables are embedded during `next build`; rebuild after changing the\nedition.\n\nCloud configuration is documented in [.env.example](.env.example). Community\nconfiguration is documented in [community.env.example](community.env.example).\nThe exact feature, data, API, and billing boundaries are documented in\n[Community and Cloud editions](docs/EDITIONS.md).\nCloud operators should also follow the\n[billing runbook](docs/CLOUD_BILLING.md).\n\n## Development\n\n```bash\nnpm ci\nnpm test\nnpm run lint\nnpm run build\n```\n\nThe stack is Next.js, React, TypeScript, Tailwind CSS, WebCrypto, Zustand, and\nVitest. Cloud deployments additionally use Clerk, Neon/Drizzle, Lemon Squeezy,\nand Vercel Analytics.\n\n## Contributing and security\n\nRead [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. Use\n`git commit -s` to certify the Developer Certificate of Origin.\n\nNever open a public issue containing credentials or a vulnerability. Follow\n[SECURITY.md](SECURITY.md) for private reporting. Community conduct is governed\nby [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), and project decisions follow\n[GOVERNANCE.md](GOVERNANCE.md).\n\n## Business model\n\nStoreOps follows an open-source-plus-hosted-convenience model without\nwithholding the core developer workflows:\n\n- Community users can self-host the full operational tool.\n- Cloud customers pay to avoid deployment and maintenance, synchronize recovery\n  data across devices, and receive direct support.\n- Sponsorships and commercial partnerships may fund additional development.\n\nBuying StoreOps Cloud does not install or switch the Community build. Checkout\nevents are accepted only by the Cloud edition, verified against the configured\nLemon Squeezy signing secret, and mapped only from StoreOps's configured yearly\nand lifetime variant IDs.\n\n## License\n\nStoreOps is licensed under the [GNU Affero General Public License v3.0 only](LICENSE).\nIf you modify StoreOps and make that modified version available over a network,\nthe AGPL requires offering the corresponding source to its users. See the\nlicense text for the controlling terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falisabry22%2Fstoreops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falisabry22%2Fstoreops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falisabry22%2Fstoreops/lists"}