# Version, support and migration contract The capability contract is **1.0.0**, with snapshot `schema_version: 1`. The injected browser SDK and MCP server report **1.5.0**. The SDK supports both `Hackemist.createProgressSaver` and `Hackemist.createProgressStore`; neither name is removed or renamed. Prefer the store for new account-save integrations because it adds explicit reconciliation and identity-bound local recovery. [The complete counter](/docs/progress-example.md) is runnable HTML; [the SDK guide](/docs/save-sdk.md) covers both controllers. SDK 1.5.0 adds optional readiness declarations and browser feature probes; it preserves the 1.3/1.4 progress-helper contracts and capability schema version 1. A creator `markReady()` event is an authored readiness assertion after useful initialization, not a substitute for gameplay or save verification. Receipt 3 records DOM startup, declared readiness and bounded resource observations. ## Discover support and effective availability `GET /api/capabilities` is an account-independent, stable support catalog. `available` there means the platform implements that contract, not that a browser, plan or deployment has enabled it. Its `availability_scope` is `support_contract_only`. It never reads users, project files, service health, private settings or credentials. `GET /api/capabilities/effective` requires a signed-in account. `GET /api/projects/{project_id}/capabilities` additionally requires current project ownership or administrator access. These private, uncached snapshots combine current plan access, site switches, configured runtime availability and approved project metadata. MCP uses the same resolver with its already-validated credential scopes and project boundary. Studio login does not authorize an MCP connection. Every operation still rechecks its own authorization and revisions. Each entry has `state`, a machine-readable `reason`, a public `documentation` path and, when useful, an `action` path. States are `available`, `disabled`, `permission-required`, `unsupported` and `unavailable`. A disabled option can be supported; an unavailable deployment prerequisite cannot be fixed by a permission grant. `available` never substitutes for API/device detection or player consent. Inspect [the JSON schema](/docs/capabilities.schema.json) and [public example](/docs/capabilities.example.json). Snapshot `revision` hashes only returned metadata; compare it for changes rather than treating it as a write guard or a publication fingerprint. `upload_policy` exposes the supported entrypoint, asset extensions, path/archive restrictions, native chunk bound and save-channel parser limits. Private `limits` uses the write paths' current plan/site quota resolver, including remaining account storage and effective upload ceilings. Numeric policy remains authoritative over descriptive prose. `versions` reports the capability/app schema, platform/SDK, readiness and static-check/report contracts. An MCP snapshot exposes only its own filtered scopes and whether its project boundary is restricted; it returns no bearer, account ID, external-origin list or private setting. Discovery performs bounded metadata reads. It does not scan app source, render frames, probe a GPU, request XR access, capture media or start checks. `readiness.state: not_evaluated` means no report was supplied. Explicit creator actions run checks; publication continues to validate current evidence. A metadata-only readiness summary does not prove gameplay, authenticated save restoration, device performance or external-service behavior. [App manifests](/docs/app-support.md) describe authored requirements and fallback choices without granting permissions. ## Validation report contract Aggregate publishing reports use `report_schema_version: 2`, contract `1.0.0` and current static rules version `5`. The independent browser checker receipt currently uses version `3`; these numbers describe different contracts. Read [the report JSON schema](/docs/validation-report.schema.json) and [synthetic report example](/docs/validation-report.example.json). The schema types the shared core and permits additional optional fields, so clients can read newer evidence without rejecting unfamiliar metadata. It describes a report, not an operation that runs validation or publishes an app. Report and finding `outcome` values are `passed`, `warning`, `rejected`, `review_required` or `inconclusive`. Inspect the outcome, findings, evidence kind, check version, remediation and environment together. No browser receipt means inconclusive browser evidence; a pending permission request needs review. A blocked optional dependency can remain a warning when a usable fallback exists. Runtime/checker/environment provenance hashes bind cached evidence to its implementation; they are not account credentials. The public example contains only synthetic identifiers and bounded aggregate observations, with no private URLs, source, player data or actual deployment hashes. Schema validation alone does not sanitize arbitrary strings. `environment.not_verified` states the scope limit explicitly. A creator readiness timestamp is an authored assertion, a first rendered frame is startup evidence, and observed resource bytes cover only measured same-origin loads. None proves all later assets, complete gameplay, authenticated saves, external services or physical-device performance. Recheck required evidence after changing the source, runtime policy, declared targets or deployed implementation. ## Compatibility and releases Schema version 1 keeps the documented field meanings. Clients should ignore additive fields and handle unknown capability keys/reason codes safely; treat an unknown state as unavailable until understood. Removing a field, changing a field's type or changing state semantics requires a new schema version and migration guidance. The revision changes when returned effective metadata changes; there is no timer-dependent revision or automatic per-view audit. An absent `hackemist-app.json` keeps an existing app's behavior. Adding the optional declaration creates no automatic permission grant or source rewrite. Existing approved origins, account saves, default-slot identities, private boundaries and published releases remain governed by their existing revision and authorization rules. Test a draft before explicitly publishing an update. A capability snapshot is information, not a completed release. ## Save-format migrations and recovery The optional `hackemist-save.json` declaration is separate from `hackemist-app.json`. The former versions saved data; the latter describes app support. Keep all durable fields compatible, or use the explicit save migration API from [the SDK guide](/docs/save-sdk.md). Preserve migration originals, validate finite JSON, wait for restoration before play, and pause for a player choice when local and cloud progress differ. A failed read is never an empty slot. A positive empty revision is a deliberate reset and must not resurrect an older local cache. Publish server identity metadata, SDK and player recovery controls together. If a server lacks stable save identity, the reconciled store fails closed. Keep existing originals and account/slot boundaries during rollback; hide a new optional interface if necessary while retaining revision and preservation gates. Do not restore an old database over current player data or clear browser storage as a repair. [Browser recovery](/docs/browser-recovery.md) documents native-storage boundaries, export and deliberate cleanup.