# App version follows semantic versioning

- **Pattern:** `ab-001952` (`mobile-store-readiness.version-management.version-semver`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001952
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001952)

## Why it matters

Non-semver strings like `1.0`, `v1.0.0-beta`, or `01.00.00` break downstream tooling that parses `app.json` — EAS Update channels, Sentry release matching, crash-report grouping, and CI/CD diff-comparison scripts all assume the `MAJOR.MINOR.PATCH` contract. When the format drifts, release notes collapse into a single bucket, regression bisects miss the breaking commit, and users cannot tell a feature release from a hotfix. Semantic versioning is also the communication channel App Store Connect and Play Console use to render "What's New" prompts correctly.

## Severity rationale

Low because malformed versions degrade tooling and release hygiene but do not compromise security or user-facing functionality directly.

## Remediation

Set the `version` field in `app.json` to three non-negative integers separated by dots and strip any prefixes or pre-release labels — those belong in `buildNumber` or a separate channel identifier. Automate the constraint in CI so a malformed value fails the pipeline before it reaches a store submission.

```json
// app.json
{
  "expo": {
    "version": "1.0.3",
    "ios": { "buildNumber": "12" },
    "android": { "versionCode": 12 }
  }
}
```

## Detection

- **ID:** `version-semver`
- **Severity:** `low`
- **What to look for:** Check `app.json` for `version` field. Count the number of dot-separated segments in the version string. Should follow semantic versioning: `major.minor.patch` (e.g., `1.0.0`, `2.3.1`). No leading zeros (e.g., `01.02.03` is incorrect), no extra labels like `alpha` or `beta` in the version field itself.
- **Pass criteria:** Version is in semver format: `X.Y.Z` where X, Y, Z are non-negative integers with exactly 3 segments separated by dots. No extra labels or leading zeros. Before evaluating, extract and quote the exact version string found in `app.json`.
- **Fail criteria:** Version uses unusual format like `1.0` (missing patch — fewer than 3 segments), `v1.0.0` (includes 'v' prefix), `1.0.0-beta` (includes label), or `01.00.00` (leading zeros). Do NOT pass when the version field is missing entirely.
- **Skip (N/A) when:** Never — version format should always be standardized.
- **Detail on fail:** `"App version is '1.0' — should be '1.0.0' with explicit patch version"` or `"Version has label 'v1.0.0-beta' — label should be separate from version field"`
- **Remediation:** Semantic versioning clarifies release importance. Use the format:
  1. In app.json:
     ```json
     "version": "1.0.3"
     ```
  2. Format: `major.minor.patch`
     - major: Incremented for breaking changes
     - minor: Incremented for new features (backwards compatible)
     - patch: Incremented for bug fixes
  3. Examples:
     - `1.0.0` — initial release
     - `1.1.0` — added new feature
     - `1.1.1` — bug fix
     - `2.0.0` — breaking change
  4. If you need to indicate pre-release status (alpha, beta), use `buildNumber` instead of modifying the version field

Taxons: operational-readiness

HTML version: https://auditbuffet.com/patterns/ab-001952
