Files
eden/docs/research/expansion-data-contracts.md
2026-09-18 23:15:05 -04:00

85 lines
9.2 KiB
Markdown

# Data contracts for the remaining-feature roadmap
**Research date:** 2026-09-19 UTC. **Compatibility pin:** `X-Compatibility-Date: 2026-08-18`.
**Scope:** official public documentation/OpenAPI research for planning. No private ESI requests, credentials, user data, archives, or service changes were used. These adapters are not implemented merely because their contracts are listed here.
Primary source: [official ESI OpenAPI](https://esi.evetech.net/meta/openapi.json), requested with the compatibility header above. Additional sources: [versioning](https://developers.eveonline.com/docs/services/esi/overview/), [pagination](https://developers.eveonline.com/docs/services/esi/pagination/x-pages/), [rate limiting](https://developers.eveonline.com/docs/services/esi/rate-limiting/), [best practices](https://developers.eveonline.com/docs/services/esi/best-practices/), and [SSO](https://developers.eveonline.com/docs/services/sso/).
Existing captured evidence in `eve-openapi-evidence.json` covers the first milestone's assets/helpers/structure topics, **not** all expansion routes below. Capture focused, versioned fixtures for each new adapter before implementation. Recheck the pinned contract at that point; advancing the compatibility date is a separate deliberate change.
## Personal-character datasets
All methods in this table are GET. Paths use the trusted `https://esi.evetech.net` base.
| Dataset | Route | OAuth scope | Pagination / historical coverage | Documented cache |
|---|---|---|---|---|
| Wallet balance | `/characters/{character_id}/wallet` | `esi-wallet.read_character_wallet.v1` | Single numeric balance | 120 s |
| Wallet journal | `/characters/{character_id}/wallet/journal` | Same wallet scope | `page` + `X-Pages`; past **30 days** | 3600 s |
| Wallet transactions | `/characters/{character_id}/wallet/transactions` | Same wallet scope | `from_id`, records before the given ID; retention/page size not specified | 3600 s |
| Open orders | `/characters/{character_id}/orders` | `esi-markets.read_character_orders.v1` | Unpaged current orders; includes `is_corporation` | 1200 s |
| Order history | `/characters/{character_id}/orders/history` | Same order scope | `page` + `X-Pages`; cancelled/expired orders up to **90 days** | 3600 s |
| Owned blueprints | `/characters/{character_id}/blueprints` | `esi-characters.read_blueprints.v1` | `page` + `X-Pages`; item/type/location, ME/TE and runs | 3600 s |
| Skills | `/characters/{character_id}/skills` | `esi-skills.read_skills.v1` | Unpaged; documented possibility of stale levels after training completion | 60 s, event-based |
| Skill queue | `/characters/{character_id}/skillqueue` | `esi-skills.read_skillqueue.v1` | Unpaged; needed to reconcile completed training with stale skill responses | 60 s, event-based |
| Industry jobs | `/characters/{character_id}/industry/jobs` | `esi-industry.read_character_jobs.v1` | Unpaged; `include_completed`; completed jobs only **90 days** | 300 s |
Planning consequences:
- Personal wallets share one scope, but balance/journal/transaction freshness and collection strategy differ.
- Do not treat `from_id` as a page number or invent a fixed transaction page size, cursor depth, or retention horizon.
- ESI retention is not application retention. Data may be retained after collection under an approved policy, but missing earlier history cannot be reconstructed by assumption.
- Do not assume order history describes every possible fill or disappearance; reconcile documented state/quantities with transaction evidence and preserve uncertainty.
- Exclude or explicitly partition `is_corporation` orders from personal financial totals. A character endpoint is not proof that every returned economic position is personally owned. Check any similar personal/corporation flags in transaction schemas during adapter implementation.
- Skills and skill queue are separate grants. Reconcile according to the documented completion behavior and timestamps; future queue entries are not trained skills, and conflicting/stale evidence must not manufacture eligibility.
- Owned blueprint instances are distinct from immutable recipe types and from the current asset-copy flag.
## Public and authenticated market feeds
| Dataset | GET route | Access | Pagination / cache |
|---|---|---|---|
| Active region types | `/markets/{region_id}/types` | Public | `page` + `X-Pages`; 600 s |
| Region orders | `/markets/{region_id}/orders` | Public; required `order_type` (`buy`, `sell`, or `all`), optional `type_id` | `page` + `X-Pages`; 300 s |
| Region history | `/markets/{region_id}/history` | Public; required `type_id` | Unpaged daily statistics; daily expiry at 11:05; retention horizon not specified |
| Structure orders | `/markets/structures/{structure_id}` | `esi-markets.structure_markets.v1` and authorized character context | `page` + `X-Pages`; 300 s |
Regional history contains date, volume, order count and high/average/low statistics. It is not a fill forecast, order book, or proof of executable liquidity. Structure-market access is not docking permission and must not become an unrestricted shared private-data cache.
The existing `/markets/prices` provider remains a different, global reference-price dataset; see [the initial ESI research](eve.md#reference-price-valuation).
## Later corporation datasets
Role declarations below come from the pinned contract, not a live corporation-role test. Verify effective role semantics, division restrictions, membership and application-workspace permissions at implementation time. A corporation scope alone is insufficient.
| Dataset | GET route | OAuth scope | Declared role requirement | Pagination / cache / history |
|---|---|---|---|---|
| Assets | `/corporations/{corporation_id}/assets` | `esi-assets.read_corporation_assets.v1` | `Director` | `X-Pages`; 3600 s |
| Wallet balances | `/corporations/{corporation_id}/wallets` | `esi-wallet.read_corporation_wallets.v1` | `Accountant` or `Junior_Accountant` | Division/balance array; 300 s |
| Wallet journal | `/corporations/{corporation_id}/wallets/{division}/journal` | Same wallet scope | Same wallet roles | `X-Pages`; 30 days; 3600 s |
| Wallet transactions | `/corporations/{corporation_id}/wallets/{division}/transactions` | Same wallet scope | Same wallet roles | `from_id`; retention unspecified; 3600 s |
| Open orders | `/corporations/{corporation_id}/orders` | `esi-markets.read_corporation_orders.v1` | `Accountant` or `Trader` | `X-Pages`; 1200 s |
| Order history | `/corporations/{corporation_id}/orders/history` | Same order scope | Same order roles | `X-Pages`; 90 days; 3600 s |
| Blueprints | `/corporations/{corporation_id}/blueprints` | `esi-corporations.read_blueprints.v1` | `Director` | `X-Pages`; 3600 s |
| Industry jobs | `/corporations/{corporation_id}/industry/jobs` | `esi-industry.read_corporation_jobs.v1` | `Factory_Manager` | `X-Pages`; completed jobs 90 days; 300 s |
No corporation-skills equivalent was verified: skills remain character-scoped. Corporation industry-job records must not be confused with the application's own `jobs` orchestration table.
## Scheduling and consistency implications
The pinned extensions identify `char-wallet` as 150 tokens/15 minutes, `char-industry` as 600/15 minutes, `char-detail` as 600/15 minutes, and regional orders as `market-order` 12,000/15 minutes. These are **tokens**, not necessarily one token per request. Confirm route-specific headers and token costs at implementation time.
Character order routes have no route-specific limiter extension in the inspected contract; that does not mean unlimited access. Respect the legacy error limiter and response caching. TTLs are scheduling hints bounded by actual response validators/cache headers, not promises that upstream content is fresh to the second.
X-Pages guidance warns that cache expiry between pages can duplicate records. Do not assume one asset-specific pagination algorithm establishes stable snapshots for every route. Preserve source IDs, idempotent checkpoints, partial/backfill status and coverage windows. Prices, journals, assets, skills and jobs do not form one atomic EVE-wide transaction.
## Concrete code integration points
- `src/lib/server/sso.ts`: authorization currently requests only assets; add server-allowlisted capability scope upgrades and state binding.
- `src/lib/server/esi/index.ts`: only assets and global reference prices currently have public client methods; implement separate typed adapters/strategies for these new routes.
- `src/lib/domain/model.ts`: add dataset/finance/owned-blueprint/skill/job contracts; existing `BlueprintRepository`/`OrderBook` are narrow placeholders.
- `src/convex/schema.ts`: add bounded records, generations/checkpoints and indexes. Its current generic `jobs` placeholder is not ESI industry-job data.
- `src/lib/server/application.ts`: existing synchronization orchestrates assets only; new datasets belong in the durable job/capability design.
## Unresolved and explicitly not promised
Wallet-transaction retention, market-history retention, exact page sizes, maximum cursor depth, complete consistency guarantees across pages/endpoints, real corporation-role behavior, fee formulas, industry economics and dynamic docking authority are not established by this research. Verify those separately; do not infer them from endpoint availability.