# Post-wipe apply order (empty tenant)

Use this after a **full tenant cleanup** (no entities, registry, `_users`, `_roles`, menus, or physical collections). Every step uses the **Seeds API only** (`POST /v1/seeds/validate` then `POST /v1/seeds/apply`). No direct Mongo edits and no ad-hoc pymongo apply scripts.

Product contract: [apply-contract.md](./apply-contract.md)

## Env

```bash
export GIA_ENDPOINT=https://gia.hub8.ai/api   # or http://127.0.0.1:4000
export GIA_API_KEY=pk_...
```

Health:

```bash
curl -sS -H "Authorization: Bearer $GIA_API_KEY" "$GIA_ENDPOINT/v1/seeds/health"
```

## Helpers (validate before every apply)

```bash
seed_validate() {
  curl -sS -X POST "$GIA_ENDPOINT/v1/seeds/validate" \
    -H "Authorization: Bearer $GIA_API_KEY" \
    -H "Content-Type: application/json" \
    -d @"$1" | tee "/tmp/validate-$(basename "$1")-result.json"
}

seed_apply() {
  seed_validate "$1" || return 1
  curl -sS -X POST "$GIA_ENDPOINT/v1/seeds/apply" \
    -H "Authorization: Bearer $GIA_API_KEY" \
    -H "Content-Type: application/json" \
    -d @"$1"
}
```

Fix every item in `errors[]` before apply. Apply aborts with HTTP **400** when validation fails (no partial writes). `warnings[]` are soft hints.

## Two paths

| Tenant goal | Playbook |
|---|---|
| **Community sample** (Golden Mini, new app from template) | [§ Golden Mini on empty tenant](#golden-mini-on-empty-tenant) |
| **Full Zyga / PCR app** (Users links, large PCR data) | [§ Zyga on empty tenant](#zyga-on-empty-tenant) |

`manifest.publishOrder` is enforced **inside each package** by the API. Cross-package order (System before Zyga) is **manual**: run steps in sequence, validate between each POST.

---

## Golden Mini on empty tenant

Golden Mini has no Users links. One package is enough for a smoke tenant.

```bash
# Hub8 invitees (community repo):
cd samples/golden-mini-seed
python3 apply_via_api.py --dry-run   # local package build only
python3 apply_via_api.py             # discover → validate → apply → verify

# Or curl the public package:
curl -sS https://gia.hub8.ai/vibe-coding/golden-mini.seed.json > /tmp/golden-mini.json
seed_apply /tmp/golden-mini.json
```

Verify: `GET /v1/entities/by-name/Demo%20Items` and relation-graph.

---

## Zyga on empty tenant

Full playbook with jq examples lives in **gia-pro** (platform maintainers):

| Step | What | gia-pro doc |
|---|---|---|
| **1** | System **Roles** + **Users** | `data/system-seed/README.md` |
| **2** | Zyga master entities (PCR Status, PCR Pending Reason, Clients) schemas only | `data/zyga-seed/README.md` § Step 2 |
| **3** | Master records | § Step 3 |
| **4** | App entities (PCR, Insights, dashboards, Zyga Home, …) schemas only | § Step 4 |
| **5** | Menus only | § Step 5 |
| **6** | PCR records in batches | § Step 6 |

Step 1 is **required** before PCR data: PCR **REVIEWER** links resolve against **Users** ids.

### Step 1: System (summary)

Build `/tmp/system-package.json` from `gia-pro/data/system-seed/` entity + record JSON with `publishOrder: ["Roles", "Users"]`. See system-seed README for the full `jq` recipe.

```bash
seed_apply /tmp/system-package.json
```

Confirm login users exist before continuing.

### Steps 2–4: Schemas in order

Each step: build package JSON → `seed_validate` → `seed_apply`.

- **Step 2:** master entity schemas, empty `records`, `skipRecords: true`
- **Step 3:** master records only, `skipEntities: true`, `matchFields` on Status / Reason / Clients
- **Step 4:** remaining entities from `MANIFEST.json` `publishOrder`, empty `records`

Or export schemas from a source tenant:

```bash
curl -sS -G "$GIA_ENDPOINT/v1/seeds/export" \
  --data-urlencode "entities=PCR,PCR Insights" \
  --data-urlencode "includeRecords=false" \
  -H "Authorization: Bearer $GIA_API_KEY" \
  -H "X-Tenant-Id: <source-tenant-id>" \
  | jq '.package | .records = {} | .options = { skipMenu: true, skipRecords: true }' \
  > /tmp/zyga-app-schema.json

seed_apply /tmp/zyga-app-schema.json
```

### Step 5: Menus

`GET /v1/seeds/export` does **not** include menu rows. Use a saved menu package from a reference tenant, or build `menu.records` from `GET /v1/menu` on a source tenant.

```bash
jq '.entities = [] | .records = {} | .options = { skipEntities: true, skipRecords: true, skipMenu: false }' \
  /tmp/zyga-menu-package.json > /tmp/zyga-menu-only.json

seed_apply /tmp/zyga-menu-only.json
```

Each menu row `Collection` must match an entity already published (step 4).

### Step 6: PCR records (batched)

Export from source tenant (includes `linkResolve` for label → id on apply):

```bash
curl -sS -G "$GIA_ENDPOINT/v1/seeds/export" \
  --data-urlencode "entities=PCR" \
  --data-urlencode "includeRecords=true" \
  --data-urlencode "recordLimit=50000" \
  -H "Authorization: Bearer $GIA_API_KEY" \
  -H "X-Tenant-Id: <source-tenant-id>" \
  | jq '.package | .entities = [] | .menu = { records: [] } | .options = { skipEntities: true, skipMenu: true, skipRecords: false }' \
  > /tmp/zyga-pcr-records-full.json
```

Validate once, then batch (500-2000 rows per POST). **Validate each batch** when tuning size:

```bash
BATCH=500
TOTAL=$(jq '.records.PCR.records | length' /tmp/zyga-pcr-records-full.json)

for START in $(seq 0 $BATCH $((TOTAL - 1))); do
  jq --argjson start "$START" --argjson size "$BATCH" '{
    name: ("zyga-pcr-records-" + ($start|tostring)),
    manifest: { publishOrder: [] },
    entities: [],
    menu: { records: [] },
    records: { PCR: { records: .records.PCR.records[$start:$start+$size] } },
    options: { skipEntities: true, skipMenu: true, skipRecords: false }
  }' /tmp/zyga-pcr-records-full.json > "/tmp/pcr-records-${START}.json"

  seed_apply "/tmp/pcr-records-${START}.json"
done
```

Master rows (Status, Reason, Clients, Users) must exist on the target tenant before PCR rows, or `link_resolve_failed` / `link_id_not_found` errors block apply.

---

## Validation error codes (common)

| Code / message | Meaning | Fix |
|---|---|---|
| `link_resolve_failed` | Linked field value could not resolve to a tenant id | Apply masters + Users first; check `linkResolve` |
| `record_link_not_id` | Link field stored a label where id is required | Fix seed or export with `linkResolve` |
| `link_id_not_found` | Id not in target collection | Apply Users / masters on target first |
| `menu_collection_missing` | Menu `Collection` entity not published | Complete entity steps before menu |
| Schema link errors | Missing `sourceLabel`, bad `valueField` | Fix entity JSON; re-validate |

---

## See also

- [apply-contract.md](./apply-contract.md): validate apply (strict)
- https://gia.hub8.ai/vibe-coding/AGENTS.md
- https://gia.hub8.ai/docs/apps/seed-packages
- https://gia.hub8.ai/docs/api
- gia-pro `data/system-seed/README.md` and `data/zyga-seed/README.md`: full jq recipes
