Skip to content

Zone payloads: deleted, zoneType unmodeled and ownerRecordName never decodes (confirmed live) #444

Description

@leogdion

Summary

A live zones/changes call against a real container returned zone objects that carry deleted and zoneType, neither of which MistKit models. deleted is the significant one: a caller currently cannot tell a deleted zone from a live one.

Evidence

POST zones/changes on iCloud.com.brightdigit.MistDemo / development / private DB, no sync token:

{
  "moreComing": false,
  "metaSyncToken": "AQAAAaBJidqD",
  "zones": [
    {
      "zoneID": {
        "zoneName": "WebChangeTest",
        "ownerRecordName": "_aca0fa3547ae9f9cd1f7e25fed948a20",
        "zoneType": "REGULAR_CUSTOM_ZONE"
      },
      "deleted": true
    }
  ]
}

Every zone in the response had "deleted": true and a zoneType inside zoneID.

Current state

After #427, the shared Zone schema in openapi.yaml models zoneID, syncToken, atomic. The domain ZoneInfo carries zoneName, ownerRecordName, capabilities, syncToken, atomic.

Neither deleted (zone level) nor zoneType (inside zoneID) is represented, so both are silently dropped on decode.

Note #427 deliberately implemented only the subset confirmed against Apple's archived reference and left unconfirmed fields out rather than guessing (see .claude/memory/reference_cloudkit_zone_dictionary.md). This issue supplies live confirmation for two more fields — the same standard of evidence, now from an actual response rather than the docs.

Why deleted matters

zones/changes is a change feed: a deleted zone is exactly the kind of change a sync client must observe. Returning it as an ordinary ZoneInfo indistinguishable from a live zone means a caller replaying changes will treat deletions as creations.

Worth checking whether changes/database (DatabaseChangedZone, the supported replacement per #401) carries the same field — it likely does, and that path is the one callers should be using.

What to do

  1. Confirm the field set against changes/database as well as zones/changes before encoding — do not assume they match.
  2. Add deleted: Bool? to the Zone schema (and DatabaseChangedZone if confirmed there), and zoneType to ZoneID, in openapi.yaml; regenerate via ./Scripts/generate-openapi.sh.
  3. Surface them on the domain types. Consider whether deleted deserves better than Bool? on ZoneInfo — a change feed arguably wants a per-zone enum (changed vs deleted), which would be a larger design change.
  4. zoneType observed value: REGULAR_CUSTOM_ZONE. Find the full set before modeling it as an enum rather than a string.

Found while verifying #430.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions