# Changelog (agent-facing)

This changelog is written for autonomous agents and integrators. It focuses on surface-area changes that matter for HTTP clients.

## phase6-v3 (2026-06-15) -- Attestation Performance, Byte-Level Verification, Self-Contained Proofs

- **Attestation latency is now flat as lockers grow.** `POST /v1/storage/attest` no longer re-downloads file bytes on every call — it trusts the per-file `content_hash` recorded at confirm time. A multi-gigabyte locker now attests in roughly the same few seconds as a small one (bounded by the on-chain Switchboard confirmation, not by locker size). No request-shape change.
- **Auto-reattestation skips unchanged lockers.** The gateway's automatic re-attest after each file confirm is now suppressed when the manifest has not changed since the last attestation, eliminating redundant on-chain transactions. Explicit `POST /v1/storage/attest` calls always re-attest, unchanged.
- **`GET /v1/storage/recompute-verify` is now a true byte-level integrity check.** It re-downloads every file from storage, re-hashes the bytes, rebuilds the Merkle tree, and compares to the persisted attestation. Use it when you need to prove stored bytes still match what was attested; latency scales with locker bytes. Plain `POST /v1/storage/verify` remains the cheap, cached structural check.
- **`GET /v1/lockers/{locker_id}/files/{filename}` now verifies object presence.** If the manifest has an entry but the underlying object is missing from storage, the endpoint returns a typed `404 CONTENT_NOT_FOUND` instead of a download URL that fails later. Clients get an actionable, distinguishable error.
- **Attestation skips files whose bytes are missing from storage.** `compute_fingerprint` now confirms object presence (parallel existence checks) before including a file, so a green attestation means "manifest + bytes present," not just "manifest entry exists."
- **`verification-bundle.payment_proof` is fully populated for every asset.** `paid_amount`, `pay_asset`, `paid_raw`, and `confirmed_at` are present for all payments (including SPL tokens). The SOL-specific `amount_sol` / `amount_lamports` fields are populated for native-SOL payments and null for SPL-token payments by design — use `paid_amount` + `pay_asset` for an asset-generic view.
- **`manifest_signature` is now a normative, fully-specified field.** The Merkle spec (`/specs/nukez-merkle-v1.json`, `/docs/verify/merkle-v1.md`) now documents the algorithm (Ed25519), the signing key (the gateway service key, published as `receipt_signer_pubkey` on `GET /v1/receipts/{id}`), the exact signed payload (the bare `merkle_root` with the `sha256:` prefix stripped, UTF-8), the hex encoding, and verification steps. Third parties can now verify the gateway's signature independently.
- **Merkle spec hardening: `file_count` binding is now a MUST.** Verifiers MUST confirm the leaf count they used equals the attested `file_count` (present in the attestation object and the on-chain SPL Memo), closing the odd-node (CVE-2012-2459) ambiguity. Filenames cannot contain `:`, so the `filename:size_bytes:content_hash` leaf material is unambiguous.
- **Discovery surfaces corrected to mainnet-only with full asset set.** `tools.json` and `tool_contract.json` now list solana-mainnet and monad-mainnet (no devnet/testnet) and include BETA (Solana) and USDT0 (Monad) in the payment enums, matching the discovery doc and `llms.txt`.
- **SDK (pynukez ≥ 4.0.20):** new methods `recompute_verify(receipt_id)`, `attest_async(receipt_id)` (sync=false + poll), `confirm_files(receipt_id, filenames)` (batch confirm — one attestation per batch instead of per file), and `download_to_file(...)` (streams to disk). Client timeouts widened; new `attest_timeout` handling.
- Discovery contract version stamped `phase6-v2-2026-06-12` in `.well-known/nukez.json` (the version label still reads phase6-v2; these are additive, backward-compatible changes — no previously-working HTTP shape broke).

## phase6-v2 (2026-05-19) -- Signed Envelope Required on Attestation Endpoints

- **BREAKING: `POST /v1/storage/attest` and `POST /v1/attest/push` now both require a signed envelope.** Previously both accepted unauthenticated requests; now both return 401 without `X-Nukez-Envelope` + `X-Nukez-Signature`.
  - `/v1/storage/attest` computes the file-set Merkle root over confirmed files.
  - `/v1/attest/push` anchors the computed root on Switchboard (PullFeed write + SPL Memo).
  - Both endpoints are gated by the same new op: `locker:attest`.
  - Envelope `receipt_id` must equal the request's `receipt_id` (JSON body for push; query parameter for attest); mismatch returns 401 `RECEIPT_ID_MISMATCH` on both.
  - Rationale: both endpoints cause the gateway to spend server-held SOL on oracle / anchor writes. Authentication binds the spend to the receipt's payer.
- **New op name `locker:attest`** — issued only by the receipt's payer key. Covers `/v1/storage/attest` and `/v1/attest/push` (and any future endpoints that anchor attestations on-chain using server resources).
- **Migration**: most clients call attestation via the SDK (`client.attest(receipt_id=…)`) or `/v1/storage/verify` — both wrappers must be updated to construct signed envelopes with `ops=["locker:attest"]`. Direct HTTP callers of either endpoint must do the same. Unsigned calls return 401.
- Discovery contract version stamped at `phase6-v2-2026-05-19` in `.well-known/nukez.json`.

## phase6-v1 (2026-04-06) -- EVM Auth + Sponsored Provisioning + Developer-Owned Lockers

- **EVM/secp256k1 auth**: Full multi-chain signed envelope support. EVM wallets (0x-prefixed) sign envelopes with `personal_sign`. Gateway infers `sig_alg` from identity format — `0x` prefix = secp256k1, otherwise ed25519.
- **Sponsored provisioning**: `POST /v1/storage/sponsored-confirm` — OIDC-authenticated endpoint for authorized services to provision lockers on behalf of developers. Developer owns the locker, no operator added.
- **Batch sponsored provisioning**: `POST /v1/storage/sponsored-confirm-batch` — provision N lockers from a single on-chain payment. All pay_req_ids must be on the same network. Payment verified against sum of all quotes.
- **Developer-owned locker model**: Lockers are owned by the developer's pubkey. Services like NukezAgent orchestrate but never hold keys — the developer signs all envelopes.
- **Per-owner locker limit**: MAX_LOCKERS_PER_OWNER (default 50) prevents runaway locker creation. Returns `LOCKER_LIMIT_EXCEEDED` (429) when exceeded.
- **Provider-aware locker terms**: `locker_terms.py` module with per-provider capacity limits (storage_limit_bytes, file_limit, egress_included_bytes). Env var overrides per provider. Not yet enforced at write time — reserved error code `LOCKER_CAPACITY_EXCEEDED` (507).
- **SOL payment error field**: `verify_sol_payment` returns `"error"` (not `"err"`) for consistency with EVM path. `storage_confirm` accepts both field names for backward compat.
- **Tags on locker records**: Tags persisted to locker index via `_record_state`. Included in `/v1/owner/lockers` response.
- **Async event loop fixes**: Blocking `time.sleep()` replaced with `asyncio.sleep()` / `asyncio.to_thread()` in operators.py, short_url.py, public_file.py. Arweave download no longer blocks the event loop for up to 14s.
- **Nonce store fix**: AppError shadow removed — nonce replay errors now go through deterministic error formatting.
- **Dead code removed**: `locker_routes.py` (broken imports, never mounted), `_save_manifest` (zero callers), deprecated GCS MetaStore migration shims.
- **Sidecar deploy**: Helius API key moved from hardcoded env var to Secret Manager (`turbo-gateway-url:latest`).
- **ENV=development guard**: Gateway rejects `ENV=development` on Cloud Run at startup.

## phase5-v1 (2026-03-06) -- Operator Delegation + Verification Bundles

- **Operator delegation (ADR-3/5)**: Register Ed25519 operator keys to perform file operations on behalf of locker owner. Cross-chain delegation supported (EVM owner → Ed25519 operator).
  - Provision-time: include `operator_pubkey` in `POST /v1/storage/signed_provision` body
  - Post-provision add: `POST /v1/lockers/{locker_id}/operators` (ops: `locker:admin`)
  - Remove: `DELETE /v1/lockers/{locker_id}/operators/{pubkey}` (ops: `locker:admin`)
  - Operators use signed envelopes with their own Ed25519 key for file ops (read, write, list)
- **Verification bundle**: `GET /v1/storage/verification-bundle?receipt_id=X` — self-contained proof package (payment proof + content proof + algorithm spec + DIY steps). No auth required. Portable and shareable.
- **Confirm upload tool**: `POST /v1/files/confirm` — explicit SHA-256 verification after upload (ops: `locker:write`). Required for sandbox/chunked uploads and content-addressed providers.
- **Manifest endpoint**: `GET /v1/lockers/{locker_id}/manifest` — full locker manifest with all file metadata (ops: `locker:read`).
- **Fetch and store**: `POST /v1/files/fetch-and-store` — server-side URL fetch + store to locker (ops: `locker:write`). SSRF-protected.
- **Multi-chain asset expansion**: WETH and USDT added to Monad testnet payment options (was: MON, USDC; now: MON, USDC, USDT, WETH).
- **FileInfo expansion**: File metadata in manifest now includes `size_bytes`, `uploaded_at`, `content_hash`, `provider`, `provider_ref` fields.
- **Batch URL operations**: `POST /v1/lockers/{locker_id}/files/urls` — batch download URL minting for multiple files.
- Discovery contract version bumped to `phase5-v1-2026-03-06`.

## phase4-v2 (2026-02-25) -- Merkle Inclusion Proofs

- **New endpoint**: `GET /v1/storage/merkle-proof?receipt_id=X&filename=Y` — returns cryptographic proof of file membership in the attested merkle tree
- Open auth (no headers required), matching `/v1/storage/verify`
- Proof response includes: `leaf_hash`, `proof` (sibling hash path), `merkle_root`, `tree_depth`, `file_entry`, `switchboard` tx data
- Walk the proof to independently verify: start with `leaf_hash`, apply each sibling step, final hash must equal `merkle_root`
- SDK: `client.get_merkle_proof(receipt_id, filename)` added to pynukez
- MCP: `nukez_get_merkle_proof` tool added (read-only, idempotent)
- Core `build_merkle_root()` function UNCHANGED — new `build_merkle_tree_with_levels()` added alongside with intentional duplication for on-chain safety
- Switchboard impact: NONE (oracle job, memo schema, push mechanism unchanged)

## phase4-v1 (2026-02-24) -- Multi-Coin Quotes + Cap Token Elimination

- **payment_options** array in 402 response: agents discover all available payment methods (SOL, USDC, USDT, MON, WETH) with live oracle-priced amounts
- CoinGecko oracle integration for MON and WETH with 60s cache + env var fallbacks
- Agent-selectable payment: `payment_chain`/`payment_asset` in confirm body
- `sig_alg` cross-check: envelope `sig_alg` validated against receipt network
- Quote schema bumped to `dl_quote_v3`
- **Cap token eliminated**: all auth now uses signed envelopes only
- Challenge/login/whoami endpoints deprecated
- Receipt-based file proxy: `GET /v1/r/{receipt_id}/f/{filename}` — permanent, no-auth access to files
- Viewer URLs use stable receipt-based download URLs (no TTL expiry)
- Gateway file viewer fix: `locker_record_path` → `locker_index_path`

## phase3-v1 (2026-02-24) -- Nukez Rebrand + Multi-Chain

- Full rebrand from DataLocker/Lockerz to Nukez
- Multi-chain payment support: Solana + EVM/Monad
- Chain-agnostic receipt fields: paid_amount, paid_raw, pay_asset
- New storage request params: pay_network, pay_asset
- Updated all headers: X-DL-* -> X-Nukez-*
- SDK renamed: pylocker -> pynukez (v3.0.0)
- Discovery contract: `.well-known/nukez.json` (schema `nukez.discovery.v1`)
- All URLs updated: `api.nukez.xyz`, `www.nukez.xyz`
- Envelope auth supports Ed25519 (Solana) and secp256k1 (EVM)

## phase2-v2 (2026-02-23)

### Phase 1 Multi-Provider Storage
- Added storage-provider selection at request time (`provider` on `POST /v1/storage/request`).
- Active provider set now includes: `gcs`, `mongodb`, `storj`, `arweave`, `filecoin`, `firestore`.
- Locker manifests now include provider metadata for file entries (`provider`, `provider_ref` for content-addressed providers).

### Arweave integration model update
- Arweave uploads are now documented as sidecar-backed Turbo signer flow (no API-key raw upload model).
- `provider_ref` stores Arweave `tx_id` for later retrieval.

### Filecoin integration notes
- Filecoin provider path uses Lighthouse/IPFS upload API and stores CID as `provider_ref`.
- Download path resolves via configured gateway with CID.

### Firestore provider notes
- Firestore database env accepts `FIRESTORE_DATABASE_ID` (also supports `FIRESTORE_DATABASE`).
- `FIRESTORE_COLLECTION` is optional; provider defaults to `nukez_lockers`.

## phase2-v1 (2026-02-08)

### Short URL Service (Provider Opacity)
- **All upload_url/download_url are now short URLs**: `https://api.nukez.xyz/f/{token}` (~170 chars vs ~600 chars for raw GCS URLs). Context window savings: ~3,000 tokens per 10-file operation.
- Agents PUT/GET to short URLs directly; gateway handles provider routing via 307 redirect. This is transparent to standard HTTP clients.
- Short URL tokens are Ed25519-signed -- independently verifiable without trusting the gateway.
- New endpoint: `GET /v1/short-url/verify-key` returns the public key for token verification.
- Provider identity (GCS, S3, Azure) is never exposed to agents.

### Token Format (v2)
- v2 tokens include the filename directly in the payload (not a hash).
- v1 tokens (fn_hash) still decoded for backward compatibility but no longer created.
- Tokens encode: locker_id, filename, method, provider, expiry, nonce, ed25519 signature.

### Storage Cleanup
- Removed `payload.bin` references -- agents use named files via create_file().
- `provision_locker_v2()` alias added for transition.
- `refresh_space()` returns clean locker metadata with file_api hints.
- Dead legacy endpoints removed.

### SDK (pynukez 2.0)
- `validate_signed_url()` now accepts short URLs and legacy signed URLs.
- Updated URL validation pattern for `api.nukez.xyz/f/{token}` format.

## phase1-v4 (2026-01-19)

- Unified discovery contract now points to `/openapi.json` as canonical OpenAPI bundle.
- File endpoints documented as **signed-envelope OR cap-token** authorized.
- `ttl_min` documented for file URL minting.
- Added explicit cap-token renewal flow (`/challenge` -> `/login`) and `cap/whoami`.

## phase1-v3

- Initial "file-first" flow: signed_provision + per-file URL minting.
