# Implementation roadmap **Status:** planning proposal, not implementation or a public-launch declaration. **Baseline:** the operator has verified real EVE sign-in, asset synchronization, and matching Assets/chat reference valuations. The latest implementation gate has 97 passing tests. **Evidence:** [architecture](architecture.md), [milestone 1](milestone.md), [verification](verification.md), [ESI research](research/eve.md), [expansion data/permission matrix](research/expansion-data-contracts.md), and [reference operations](reference-operations.md). ## 1. Decisions confirmed for this roadmap 1. **Inventory and personal finances deliver the next user-visible value.** 2. **Eventually support open public signup**, not just a private installation. Public signup does not make anybody's character data public. 3. **Keep EVE-only sign-in.** Explicitly linked characters remain attached to one application user; an owner hash is never an EVE-account grouping key. 4. **Include corporation features later**, behind a separate authorization/sharing design. 5. Retain Bun/TypeScript, SvelteKit/Svelte, Convex for application state, immutable reference SQLite, Infisical, and single-host Compose initially. Do not introduce another database or model provider without a measured need and a separate decision. 6. This roadmap is **read-only intelligence and planning**: no automatic market orders, ISK transfers, asset moves, industry-job submission, or ship movement. New service/table/path names below are proposed implementation boundaries, not existing APIs. Later phases need focused design and current contract verification before coding; they are not one large implementation task. ## 2. What exists versus what still needs building | Area | Current implementation | Important gap | |---|---|---| | Identity | Verified EVE SSO/PKCE, encrypted grants, explicit linking, opaque sessions, app JWTs | Recovery, unlink/delete, transfer lifecycle, incremental scopes, session management, multi-character live tests | | Assets | Complete staged snapshots, tenant gates, exact reference totals | Real search/filtering, paging, containment, custom names, meaningful locations, history | | References | 53,001 types; recipes, dogma and system/gate tables; immutable publication | Runtime reader exposes only types/version; station table currently empty; search and domain-specific readers missing | | Prices | Global ESI average prices, held by the web process | Durable public feed coordination, regional/private books, history, depth allocation, fees | | Sync | On-demand work inside web requests; generation publication and token CAS | `jobs` is schema-only; no durable dispatcher, crash recovery, shared refresh lease or global worker budgets | | Finances | Signed integer-cent money helpers | Wallets, journals, transactions, own orders, history/coverage and reconciliation | | Industry | Recipe data plus placeholder interfaces/economics fields | Owned blueprint instances, skills/jobs, facility assumptions, formulas and optimizer | | Navigation | Exact light-year distance helper and universe data | Gate-distance service, ship-aware capital graph, dynamic constraints and qualified access evidence | | Assistant | Two typed intents and exact `/assets` / `/value`; shared deterministic report | Validated parameters, entity clarification, more capabilities, history, grounded explanations | | Operations | Working development deployment and secure secret injection | Restore-tested backups, key rotation, deletion/retention, capacity/abuse controls, staging/release gates | **Do not count placeholders as features:** `jobs`, `userPreferences`, and `referenceSyncMetadata` in `src/convex/schema.ts` are not implemented services. `OrderBook`, `BlueprintRepository`, and `CapitalRouter` in `src/lib/domain/model.ts` need richer contracts before use. ## 3. Recommended delivery order | Milestone | User-visible outcome | Dependencies | Relative size | |---|---|---|---| | M0 — Reliable account/data foundation | Clear connection/sync status; safe upgrades and recovery | Current baseline | L | | M1 — Useful inventory | Find items by character/location; browse containers; saved views and export | M0 dataset/scoping slice | L | | M2 — Personal finances | Wallets, activity, own orders, and an explained wealth overview | M0 for ingestion; M1 also required for wealth | L | | P — Public beta and signup gate | Other people can safely use isolated accounts | M0 + M1 + M2, launch checklist | L | | M3 — Market-aware valuation | Venue-specific replacement, liquidation and sell-order scenarios | M0 + M1; M2 for own orders | L | | M4 — Manufacturing planner | Feasible build candidates and auditable costs/profit | M1 + M3 + blueprint/skill/job feeds | XL | | M5A — Advanced production | Multi-stage build/buy, invention/reactions and constrained planning | M4 | XL | | M5B — Trading/procurement | Depth- and budget-aware arbitrage and shopping plans | M2 + M3 + gate-distance service | L–XL | | M6 — Capital logistics | Ship-aware jump plans with fuel/assumptions/access evidence | M0 + M1 + character skills; independent of advanced industry | XL | | M7 — Corporation workspaces | Authorized shared corporation assets/finances/industry | P + reusable personal services + corporation policy | XL | | M8 — Broader intelligence | Cross-domain assistant, grounded EVE Q&A and alerts | Shipped domain services; incremental throughout | L–XL | Sizes describe uncertainty and surface area, **not calendar commitments**: S = focused existing surface, M = several layers, L = a new subsystem, XL = multiple separately testable slices. Re-estimate each milestone after its contract/design spike. Inventory and finance work can proceed privately while the rest of M0/public hardening is completed. Wallet ingestion can run alongside M1 after dataset/scope/job foundations; the combined wealth report waits for both. Define identity/scope/revocation and grant-revision semantics before finalizing the worker model, even if the full lifecycle UX ships later. **P is a release gate, not permission to defer safety until after public signup.** Markets, industry, navigation and corporations do not need to be finished before a limited inventory/finance beta. M5A, M5B and M6 can later progress independently once their inputs exist. ## 4. Shared implementation rules ### One service result, two interfaces Every feature gets a deterministic service, conventional UI, and typed assistant adapter. Both consume the same validated request/result contracts and provenance. No parallel chat-only finance engine. Extend the capability registry to declare: - Supported operation and parameter schema. - Required datasets/scopes and selected character/resource scope. - Freshness/completeness policy and explicit missing requirements. - Server-derived principal and authorization revision. - Result schema, assumptions, exclusions, source timestamps and versions. A user/character ID supplied by a browser or JEV is a selector, never authorization. Resolve entities against the caller's allowed set; clarify ambiguous names. Do not broaden an unsupported filtered request into an all-assets answer. ### Immutable generations and honest coverage Use per-dataset states rather than making the current asset state stand for wallets, skills and everything else. A proposed `datasetSyncStates` record identifies principal, character/resource, dataset, grant revision, active generation or coverage checkpoint, status, timestamps and redacted failure category. - Snapshot datasets stage and validate before publishing a generation. - Append-oriented datasets use idempotent source-ID ingestion, bounded pages/checkpoints and explicit coverage windows; they must not pretend to have an atomic unlimited history. - Reports pin the selected input generations/checkpoints, reference version, price snapshot and assumptions. ESI is not a cross-endpoint transaction: show source skew and unavailable components. Keep fetch/revalidation time separate from an upstream effective timestamp; when the latter is not supplied, leave it unknown. - New auth/scope state invalidates affected jobs and private caches. Keep old generations for controlled recovery only; do not silently serve them as currently authorized/fresh data. - Pagination and exports use the **same query scope and pinned inputs** as the summary. Totals cover the selected result set, not just the visible page. ### Money and inventory correctness Reuse integer-cent arithmetic in `src/lib/domain/money.ts`. Add a shared, lossless **signed decimal ingestion** policy: the current ESI price converter is private and intentionally non-negative, while wallet debits and profit can be negative. Fix the UI money formatter for negative values before finance delivery. Keep ESI int64 event/order IDs and cursors as decimal strings through requests, persistence and UI. Validate quantity bounds or retain a lossless representation; never silently coerce an out-of-range value through JavaScript `Number`. Keep valuation methods distinct. Never quietly replace an average price with an adjusted price, best order, or zero. Track exclusion reasons and unit rounding. Wallet cash, open-order commitments, listed goods, industry work-in-progress and inventory can overlap: build a documented reconciliation model before summing them into wealth. ### Data boundaries - Public reference facts stay in immutable SQLite; extend its schema/readers through versioned compiler builds. - User state, financial records, jobs, saved reports and permission metadata stay in Convex initially, with indexes and bounded operations. - Dynamic prices remain outside the immutable reference database. Start with bounded watched-venue/item feeds behind a market repository contract. Benchmark storage/query/write volume before selecting the production order-book backend; no automatic universe-wide ingestion or unapproved database migration. - Public regional market caches may be shared. Authenticated structure-market/location data must stay authorization-context scoped unless an explicit, valid sharing policy applies. - Never send grants, cookies, wallet journals or whole asset inventories to JEV/research services. User-entered text sent for classification still needs public-facing provider/privacy disclosure and bounded retention/spend. ## 5. M0 — Reliable account and data foundation ### Deliverables / work packages **M0.1 — Reproducible release and safety baseline** - Review secret exclusions and establish an operator-approved version-controlled baseline; no commit is performed by this planning work. - Add isolated CI for tests/typecheck/build, deployed-artifact checks, migrations and browser flows. - Add durable browser regression coverage for native POST forms, OAuth redirect/cookie paths, singleton/array scopes, linking, logout and pending-request resume. Use synthetic providers/users only in isolated test deployments, never the persistent live backend. - Version application images; keep backwards-compatible migrations and an explicit rollback procedure. - Define and implement server-side rollout gating; it does not exist today. A deployment configuration/capability allowlist may suffice initially, but the mechanism needs approval and tests. Gates must protect routes, assistant dispatch, jobs and subscriptions—not merely hide UI controls. **M0.2 — Dataset capabilities and incremental consent** - Extend the model/gate/store contracts for dataset-specific scopes and freshness. - Replace `EveSso.authorizationUrl`'s hard-coded asset-only request with a server allowlist selected by capability. - Bind requested scopes, operation/link intent and initiating session to one-time OAuth state; save actual verified grants, not requested grants. Preserve required existing scopes deliberately, and handle denied/reduced grants without discarding the account. - Add character management: scope/status summaries, explicit upgrade/reconnect actions, per-dataset sync and cancellation. - Extend the centralized ESI transport with typed endpoint/pagination strategies and explicit read-only POST helpers, not an arbitrary URL/method executor. Asset-name/location lookups need lossless outbound int64 JSON and cache keys including canonical request bodies/auth context. Do not reuse safe-read retry rules for OAuth exchange/refresh. **M0.3 — Durable Bun sync worker** - Implement `jobs` rather than adding more long-running work to `POST /api/sync`. - Add deduplication, typed job states, due times, bounded attempts, cancellation, lease heartbeats/fencing and dataset generation/checkpoint publication. Distinguish server-owned reference/public-feed jobs from user-owned jobs and later corporation jobs; callers cannot promote their own job to system authority. - Use at-least-once job delivery with fenced, idempotent publication—not an exactly-once promise for remote OAuth calls. Renew leases during long paging/staging work; the current five-minute asset lease can be exceeded by large account syncs. - Share a per-character credential-refresh lease across web/worker processes; existing CAS alone cannot prevent two remote refresh calls. - If a refresh/code exchange result is uncertain or lost after rotation, do not blindly replay it. Persist an actionable reauthorization state where safe recovery is impossible. - Centralize scheduling/cooldowns across workers and share public feeds; respect ESI TTLs, per-character/group limits and the legacy host error budget. Add per-user queue fairness and backpressure. - Keep heavy reference extraction in its separate bounded worker; publish small reference health metadata to Convex only. Give each worker only its required secrets/capabilities; reference extraction needs no EVE grants, JEV key, JWT signing key or deployment-admin credential. **M0.4 — EVE-only identity lifecycle** - Treat each linked character as a login credential under the existing model. Explain that anybody able to authenticate as one of those characters can access the application account: linking is not merely read-only data sharing. Test transfer, revocation, unlinking and loss of access. - Require fresh proof through an already trusted login character for sensitive account actions; the new character being added is not sufficient step-up proof for adding a login credential. List/revoke sessions and detach credentials safely. Review host-bound cookie naming and test sibling-subdomain cookie injection/session fixation before public launch. - Make session replacement and prior-session revocation atomic where possible, otherwise explicitly compensating. Revalidate the initiating link/session authority at persistence time. Test failures after grant/session persistence but before old-session revocation or browser-cookie delivery; the current callback spans separate operations. - Until an approved recovery mechanism exists, reject unlinking the final login character; account deletion is a separate confirmed action. No password/code-only login or recovery is introduced by this plan. If every linked character is inaccessible, explicitly accept/document loss of access or obtain approval for a different recovery policy before P. - Reauthenticating an existing linked character restores the same application account. Explain that users must first sign into that account before linking a new alt. A signed-out login with an unlinked alt can create a separate application account; matching owner claims must not merge them. Document accidental-duplicate handling: authenticate the accounts separately, explicitly export/delete an unwanted account if chosen, then relink only after its binding is safely released. Do not silently migrate its history. - A new owner of a transferred character must never inherit the old user's history or account. Quarantine/reconcile ownership changes and invalidate affected credentials/sessions; never merge accounts or trust character names as recovery proof. Test that a verified new owner can eventually obtain a separate active binding without the old row permanently blocking signup, and that unrelated old-user characters remain separate. - Disable local access/cancel jobs first when removing authorization, then attempt remote revocation and purge credentials. If retry requires retaining token material, use a short-lived encrypted revocation-only outbox with no active-sync access and an explicit deletion deadline. Report unavailable EVE revocation as a cleanup obligation, not successful remote revocation. **M0.5 — Retention, backup, restore and rotation** - Define bounded retention for staging data, completed raw generations, journals, interactions, exports, jobs, audit events and deleted accounts. Retained summaries must not silently defeat deletion requests. - Replace unbounded full-report interaction payloads with versioned, size-limited summaries and input references. Specify what happens when referenced detail expires; do not duplicate entire inventories/journals into conversation history or claim expired detail is reproducible. - GC may not delete ACTIVE/PREVIOUS artifacts or generations still referenced by valid report cursors/jobs. - Restore-test Convex data **and instance credentials**, reference manifests/artifacts, Infisical/key backups and configuration in isolation. - Handle post-backup refresh-token rotation: a restored old token is not necessarily usable. Invalidate restored sessions before reopening traffic and flag grants needing reconnection. - Design versioned encryption envelopes/key IDs, multi-key migration, fencing with token refresh, signing-key overlap and coordinated bridge-key rotation. Do not regenerate encryption keys over existing ciphertext. **M0.6 — Reference release operations** - Schedule metadata checks and bounded rebuilds; keep compatibility-date/schema upgrades reviewed rather than automatically following today's date or a new upstream contract. - Record release/alias/resolved-source provenance, integrity limits and unsupported members. Locally computed hashes are not upstream signatures; validate published authenticity evidence when available without claiming it exists today. - Test new release fixtures, offline replay and rollback; measure peak memory/disk/time, set worker limits and reclaim only unreferenced artifacts/archives. - Require the deployed web reader to verify the actual mounted production artifact after promotion. An HTTP 200 login page or successful worker stdout does not prove catalog readiness. ### Primary code surfaces `src/lib/domain/{model,capabilities}.ts`, `src/lib/server/{application,sso,security,store,http}.ts`, `src/convex/{schema,functions,status}.ts`, auth/sync/session routes, a proposed `workers/sync.ts`, Compose/operator tooling and tests. ### Acceptance gate - Two isolated users cannot cross-read/query/export each other's data, including via borrowed cursor/job/report IDs. Same-character reauthentication returns the same account; different characters do not merge merely because owner claims match. Explicit linking and duplicate-account handling are tested. - Native browser login/refresh works with singleton and array scopes. Changed/revoked initiating sessions cannot hijack linking. Inject failure after login persistence, after old-session revocation, and before cookie delivery; reconcile unissued sessions within a bounded deadline. Retrying after an uncertain callback cannot replay a consumed OAuth code or create duplicate accounts/unbounded active orphan sessions. - Once transfer/revocation is detected, active private reads/downloads and scheduled jobs stop; credentials are invalidated or restricted to bounded revocation cleanup. The new owner receives none of the old user's snapshots, history, exports or financial data. Define and test the maximum stale-authority window rather than promising instantaneous EVE revocation detection. - Worker termination/restart, lease expiry, duplicate jobs, scope loss and uncertain token rotation cannot overwrite newer valid state, including through a stale worker's failure report. - Limits for linked characters, assets/pages/chunks, concurrent jobs and exports are explicit. Convex transaction/read/write limits and existing hard caps are exercised. Reaching a cap fails visibly without truncating and publishing a supposedly complete dataset. - An isolated restore and migration rollback are demonstrated. Public quota, retention and recovery policies are documented; no unlimited defaults are assumed. ## 6. M1 — Inventory that is useful every day ### Deliverables 1. **Reference and location readers:** indexed normalized type-name search, group/category lookups, systems/regions and NPC stations. Import a verified station source; the current empty table is not coverage. Add private structure-name resolution with explicit scope upgrades and per-character evidence caches. 2. **Inventory read model:** generation-bound indexed rows/projections for queries instead of repeatedly returning all raw asset chunks. Extend ingestion/domain/Convex schemas to retain ESI `is_singleton` as `isSingleton`, alongside parent, location type/flag and blueprint-copy fields. The current model drops it. Preserve validated source facts and stage derived indexes before publication; legacy rows with missing fields remain unknown until refreshed, not guessed from quantity. 3. **Search/filter/grouping:** item or custom name, character, category/group, quantity, location/system/region, priced/unpriced and blueprint-copy state. Provide stable server-side sorting/pagination and selected/all-character coverage. 4. **Containment:** ship/container contents, fitted flags and breadcrumbs. Resolve item-parent relationships without numeric-ID guessing; detect cycles, missing parents and ambiguous/stale locations. Never multiply hull value by contents. 5. **Saved views and exports:** schema-validated filters/preferences instead of arbitrary `v.any()` payloads, CSV and user-private report links. Use unguessable or authenticated identifiers, but never treat possession of an ID as authorization. Recheck tenant, selected resources and authorization revision on every query/download. Keep generated files out of public static storage, bound size/duration/retention, and handle account deletion. Escape spreadsheet formula injection; no public share links by default. 6. **Limited history:** snapshot differences and retained summary checkpoints, labelled as observations rather than inferred trades. Do not fabricate history predating collection. 7. **Assistant parity:** validated item/location/character parameters, deterministic entity resolution, clarification and the same filtered report/summary as the UI. ### Proposed surfaces Inventory query/result contracts; `InventoryQueryService`/`LocationService`; generation-indexed Convex projections; new reference repository methods; ESI asset-name and structure helpers; `/assets` and shared result components; assistant intent/parameter handling. Extend or wrap `AssetService` rather than cloning its authorization/valuation rules. ### Acceptance gate Tests cover singleton versus stackable items, legacy missing fields, nested containers, fitted items, blueprint copies, identical custom names, unknown structures, very large IDs and missing parents. Sorting/page boundaries are stable against a pinned snapshot. Selected totals equal aggregation over all matching rows, not the current page; they match the assistant. Forbidden structures remain unresolved rather than leaking another character's cached name. Saved-view validation and borrowed report/export IDs cannot bypass tenant or grant-revision checks. Losing access invalidates future downloads/cursors; already downloaded files cannot be recalled. Oversized or timed-out queries/exports fail visibly within measured Convex/resource budgets without partial-as-complete output. ## 7. M2 — Personal finances and an explained wealth overview M2.1 can proceed in parallel with M1 once M0's dataset/scope/job foundations exist. M2.2 follows finance ingestion; M2.3 waits for M1 and tested component reconciliation. ### Deliverables **M2.1 — Wallet balances and activity** - Character balances, signed journal entries, market transactions and independent freshness indicators. - Dataset-scoped opt-in authorization, incremental collection, deduplication by documented source identity, bounded historical backfill and explicit gaps. Journal history is limited to 30 days by the pinned contract; transactions use `from_id` and have no verified retention horizon. Do not apply one paging/backfill strategy to both. - Search/filter cash activity by character, time, reference type and counterparty; classify categories deterministically before optional semantic presentation. - Use journal entries as the ledger source and transactions as trade detail: do not sum the same cash movement twice. Match internal transfers only with reliable evidence, not merely equal amounts/times. **M2.2 — Own orders and financial context** - Active/historical personal orders, remaining quantity, order state and documented escrow/commitment semantics. Character orders can carry `is_corporation`; exclude those from personal totals until the corporation authorization/workspace phase. Open character orders are unpaged; history is paged with a documented 90-day horizon. - Treat an order disappearing from a snapshot as unknown until history/transactions establish filled, cancelled or expired state. - Keep cash balance, locked/committed funds and estimated remaining listed goods separate until a tested reconciliation policy says how they combine. **M2.3 — Wealth dashboard and history** - Compose wallet cash plus **explicitly labelled reference-valued** inventory and separately explained other components. Show gross components, overlap exclusions, missing inputs and source times. Contracts/collateral, industry work-in-progress and other unmodelled positions must be named exclusions—not silently included in a supposedly complete net worth. - Record valuation method/reference/price/input versions with historical points. Never backfill past wealth from today's prices/current inventory; later restatements need separate labels. Asset-price appreciation is not realized trading income, and missing journal history prevents claims of lifetime profit or exact reconciliation. - Budgets/watchlists/summary exports and the same typed finance queries in chat. Default privacy is per application user; no public portfolio or leaderboard. ### Proposed surfaces Wallet/finance/order repository ports and services; Convex balance snapshots, journal/transaction records and checkpoints, order state/history, financial summaries; ESI wallet/order adapters; a compact finance UI and shared money formatter. ### Acceptance gate Negative/large balances and debits preserve exact cents through lossless JSON ingestion, signed decimal normalization, totals, charts and export, with explicit rounding and negative-format tests. Journal/transaction/order IDs and cursors above `2^53` remain decimal strings. Re-fetches and overlapping/out-of-order pages are idempotent by principal, dataset and external ID. Finite source history/gaps are visible. Paired internal transfers are not income; ambiguous matches remain unclassified. Inventory, orders and cash cannot be counted twice. Partial datasets do not masquerade as complete wealth/profit. UI and assistant produce matching results for a pinned report. ## 8. P — Public beta, then open signup Start with a controlled beta; open registration only after the following evidence exists. No public hostname, capacity target, launch date or availability promise is selected by this document. - **Identity:** EVE-only recovery/last-character policy implemented and tested; sensitive actions reauthenticated; account deletion/export, transfer handling and session revocation work. - **Isolation:** adversarial two-user tests across every query, mutation, reactive subscription, job, cache, export, history and assistant path; later corporation access is independently gated. - **Live verification:** record a separate consenting-character matrix for first login, second-character linking, signed-out same-character reauthentication, incremental/reduced scopes, refresh rotation, grant revocation/reconnect, and logout/session revocation. Reuse existing valid first-login/assets evidence rather than needlessly repeating it. Exercise callback/logout backend outages in an isolated staging deployment. Record actual owner-transfer verification only when a legitimate consenting case exists—do not buy/transfer a character just for a test. Any untested provider behavior remains explicitly unverified and needs a conservative policy or launch-blocker decision before P. - **Abuse/cost:** configurable signup admission, character/dataset/job limits, per-user and global ESI/JEV budgets, request/token/output bounds, concurrency limits and provider kill switches. Gate paid inference before calling JEV; anonymous users can retain deterministic connect/manual-command flows without unrestricted paid classification. Do not rely only on process-local IP windows or trust arbitrary forwarded headers. - **Deployment:** separate staging/production data and secrets within the operator's existing Infisical project; confirm public hostname/callbacks and data migration explicitly. Keep the current development deployment intact. Never copy encrypted data and then casually replace its key. - **Ingress:** restrict direct wildcard-bound ports to intended ingress; keep admin endpoints private. The optional dashboard must remain disabled/private; if deployed outside development, pin a tested image digest instead of `latest`. Remove the main-app Pangolin login gate only as an explicit public-launch action. Validate HTTPS, secure cookies, WebSockets, proxy trust and callback/query redaction in proxy logs. - **Security:** review dependencies, authorization and cryptography; test CSP compatible with Svelte/Convex, referrer policy/native forms, clickjacking, exports and secret-free artifacts/diagnostics. Red-team prompt injection and tenant-bound parameter selection. - **Operations:** measured load/soak tests, disk/queue/ESI budgets, alerting, tested backup/restore/rotation/deletion, incident and outage procedures. Define capacity, retention, RPO/RTO and maintenance expectations before publishing them. - **Product/privacy:** permissions explanation, data retention/deletion and external-model disclosure, CCP attribution/terms review, accessible keyboard/mobile flows and safe error/support references. Infrastructure operators remain trusted; this is not zero-knowledge storage. - **Release:** migration rehearsals, immutable release identifiers, rollback and staged feature flags. Keep fixtures/synthetic write smoke tests on isolated backends; real production checks use explicit consenting accounts. ## 9. M3 — Market data and realistic valuation modes ### Deliverables - Public regional/venue order books for a **bounded configured universe**, plus authenticated structure books when explicitly authorized. Start narrow; measure before increasing coverage. - A richer market snapshot contract: order IDs, side, venue/system, range/minimum volume, remaining depth, timestamps, completeness, source/auth context and version. - Gate-distance/location eligibility needed for ranged buy orders. Market range is not Euclidean light-year distance. - Depth-consuming replacement and estimated liquidation scenarios. Deduplicate order identity across eligible feeds; allocate a shared book once across all included stacks/characters, never reusing the same remaining volume per row. - Explicit taxes/fees/standing/skill assumptions, minimum-volume rules, inaccessible/private locations and unfilled residuals. Start with user-confirmed fee-rate assumptions; automated rate derivation waits for the relevant skill/standing adapters, avoiding a dependency cycle with M4. Distinguish local proceeds from a hypothetical destination sale with separately modelled transport cost. - Sell-order scenarios with evidence-based volume/competition assumptions and uncertainty; no guaranteed fill time or executable quote. - Reference estimates remain available as their existing, explicitly selected method—not silently upgraded into Jita prices. ### Acceptance gate Golden scenarios cover insufficient depth, shared-order exhaustion, minimum-volume boundaries, order range, stale/partial pages, own-order interactions, missing fee inputs and private-cache isolation. Every result explains gross amount, costs, eligible/filled quantity, residuals and observation time. A fresh ESI snapshot is still not an execution guarantee. ## 10. M4 — Manufacturing planner ### Deliverables - Sync owned blueprint **instances** (BPO/BPC, ME/TE, remaining runs), trained skills, skill queue, current industry jobs and input availability. Reference recipes alone do not establish ownership or eligibility. Reconcile documented stale skill levels with completed queue entries; do not count future training as current eligibility. Completed industry-job history is limited to 90 days, not a complete production ledger. - Extend recipe/skill/dogma readers; explicitly block or exclude recipes with unresolved inputs rather than treating the 21 currently dangling references as zero-cost materials. - Versioned material/time/job-cost calculations, using verified current rounding rules and independent worked examples. Require facility/system/rig/service/tax assumptions; distinguish verified data from user assumptions. - Use adjusted prices only where the verified installation-cost formula requires them, never as a fallback asset sale valuation. - Basic manufacturing feasibility and bounded candidate enumeration; compare using selected market scenarios from M3. - Separate revenue, additional cash, owned-material opportunity value, economic cost, cash-flow gain, economic profit/margin, production time and ISK/hour. State blueprint acquisition/amortization and consumed-copy cost policies; do not silently price an unknown BPC or other consumed input at zero. - Plans account for blueprint runs, skills, materials, current jobs, slots, budget and location; projected output is not already-owned inventory. ### Acceptance gate Known jobs match independently checked material/time/cost examples. BPC run limits, insufficient skills, occupied slots, missing facility assumptions and unsellable outputs produce actionable constraints. Shared materials and market liquidity cannot fund/sell multiple candidates simultaneously in a selected plan. “Owned materials are free” is never used to claim profit. ## 11. M5 — Advanced production and trading branches ### M5A — Production optimization Add build-versus-buy dependency expansion, component/capital chains, invention/copying/research/reactions, batch/slot scheduling and procurement. Probabilistic outputs need expected values **and variance/assumptions**, not guaranteed quantities. Bound search, detect recipe cycles, report unmodelled mechanics and label heuristic versus proven optima. Evaluate a solver only after benchmarking bounded deterministic approaches behind a planner interface. Acceptance: no double allocation of shared stock/blueprint runs/slots/cash, correct stochastic accounting, reproducible plans and useful timeout/partial-search results. More recipes in SQLite alone are not an optimizer. ### M5B — Arbitrage and procurement Add watched-item/venue opportunities, source ask-depth consumption, destination bid-depth consumption, taxes, transport/cargo/budget constraints and opportunity expiry. Gate-route distance can support basic hauling assumptions; capital logistics is a later enhancement, not a prerequisite for all trading. Acceptance: exclude stale/negative-net opportunities, reserve shared liquidity across recommendations, account for cargo/fees, and never present turnover estimates as guaranteed profit. Outputs are explainable shopping/sale plans, not automatic orders. ## 12. M6 — Capital navigation and qualified access ### Deliverables - Separate gate and jump legs; index immutable system coordinates for bounded range-neighbour searches. Add verified space/ship-classification metadata where current readers are insufficient; security status or geometric proximity alone does not make a system jump-eligible. Reuse the exact `9,460,000,000,000,000` metre light-year constant. - Verify hull base range, calibration/eligibility and current jump restrictions; add fuel/cargo, cyno availability/type, cooldown/fatigue and timing assumptions where the available data supports them. - Avoid systems/regions and unsupported spaces; offer explicit objectives such as fewer jumps, fuel or qualified dockable stops. Return “no feasible route” rather than violating constraints. - Per-character, per-structure, per-ship-class access evidence with TTLs and limitations. Visibility and ACL membership alone do not establish docking. A Fortizar preference cannot make it suitable for a ship class that cannot dock there. - Support explicitly entered/verified waypoints where ESI cannot enumerate private structures, cynos or access relationships. Mark coverage gaps; do not claim a complete structure catalogue or real-time safety. - Enrich the placeholder `CapitalRouter` result with typed legs, distances, fuel, required assumptions, evidence, objective terms and completeness instead of a bare system list/weight. ### Acceptance gate Reference route fixtures cover boundary distances, unsupported hulls, blocked regions, disconnected space, differing skills, fuel/cyno limits, ship-class docking restrictions and expired access evidence. A geometric route is not presented as executable or safe. Live observation tests use consenting characters and do not move ships. ## 13. M7 — Corporation workspaces (later) A corporation is a distinct authorization resource, not another character on an application user. - Design explicit workspace membership/permissions, qualifying credential providers and dataset-level EVE scope/role checks before ingestion. - Verify corporation membership and current roles; invalidate authority on role loss, transfer, departure or revoked credentials. A valid character JWT alone does not grant corporation access. - Reuse snapshot/jobs/financial/industry services through an explicit resource-principal contract. Never substitute a browser-provided corporation ID for an authorized principal. - Add corporation assets, wallet divisions/activity, blueprints/jobs and relevant orders, with endpoint-specific roles and division restrictions verified from current contracts. - Separate personal portfolios from shared corporation reports. Workspace members do not automatically receive each other's personal wallets/assets. - Define credential-provider departure, administrator succession, multiple providers, account deletion and corporation data-retention policies; do not leave authority anchored to one departed director. Acceptance: endpoint/role/division permission matrix, immediate local revocation/fencing once changes are observed, stale-authority behavior, provider failover without credential leakage, personal/corporation isolation and adversarial multi-user workspace tests. Earlier personal feature completion does not waive this gate. ## 14. M8 — Assistant, knowledge and alerts Ship assistant coverage with each domain milestone rather than leaving chat unsupported until the end: - M1: typed inventory filters and entity clarification. - M2: wallet/activity/wealth queries and explicit time windows. - M3–M6: valuation scenarios, build/trade plans and routes with source-backed explanations. - M7: explicit personal-versus-corporation context and authorization checks. Then add user-scoped conversation history, saved questions, reusable scenario inputs, comparisons, and in-app alerts on typed conditions evaluated against completed snapshots. Deduplicate alerts, respect quiet/rate limits, and recheck access at delivery/read time. External notification channels need separate privacy/egress decisions. Broader EVE Q&A should retrieve curated/versioned public sources with citations and freshness, distinguish game knowledge from private live account facts, and abstain outside evidence. JEV currently supplies typed classification, not an established general-purpose answer generator. Evaluate synthesis capability/provider/privacy/cost before adding a generative model; never give it arbitrary SQL, URLs, credentials or authority over arithmetic/actions. Acceptance: per-capability adversarial/evaluation corpora, measured routing/clarification accuracy rather than assuming 0.80 is calibrated, shared UI/chat report equality, explicit stale/unknown responses, tenant-safe history and no secret/private-dataset leakage to external models. ## 15. First implementation batch after this plan Keep the initial branch focused; do not start every milestone at once. See the [parallel-worktree task plan](parallel-worktrees.md) for first-batch task briefs, dependencies, file ownership and merge order. | Work item | Concrete output | Proof of completion | |---|---|---| | 1. Baseline/release safety | Isolated test/deploy fixture and backup/migration rehearsal | Existing 97 tests remain green; restore runbook exercised without touching live test identities | | 2. Dataset, scope and identity contracts | Typed dataset status, scope-upgrade binding, grant revisions and revocation/transfer semantics | Scalar/array grants, reduced scopes, explicit linking, stale-session and job-invalidation tests | | 3. Durable asset job slice | Queue/worker/lease/refresh fencing for the existing asset endpoint | Kill/restart/duplicate/uncertain-refresh tests preserve good generations | | 4. Reference/location slice | Runtime search/group/system/station readers + verified station import | Versioned artifact tests; unknown/private locations stay unknown | | 5. Inventory query slice | User-bound filters, stable paging, complete selected summary | Cross-user cursor tests, large-account tests, UI/chat parity | | 6. Inventory UX slice | Search, character/location selectors, containment, saved view/export | Native-browser/keyboard tests and operator walkthrough | | 7. First finance slice | Wallet balance dataset and separately labelled dashboard component | New-scope consent, exact signed money, incomplete-coverage tests | After the foundations, work items 4–6 (inventory) and 7 (wallet balances) can proceed in parallel; a combined wealth report cannot. Complete the remaining M0 lifecycle/public controls before P even if these private-use slices ship earlier. Journal/transaction history and own orders follow wallet balances as separately reviewed vertical slices. ## 16. Decision and verification register | Decision / uncertainty | Resolve by | Required evidence | |---|---|---| | EVE-only recovery, duplicate accounts and last-character unlink | M0.4, before P | Same-known-character reauthentication; no standalone recovery-code/password authenticator or owner-claim merge. Document duplicate-account handling and all-character-loss policy; changes to recovery proof require separate approval | | Public admission/capacity and operating budget | M0/P | Target users/characters, sync freshness, ESI/JEV budgets, measured load and disk model | | Retention, exports/deletion and RPO/RTO | M0/P | Approved policy plus GC/restore/deletion rehearsals | | Refresh uncertainty, job leases and callback recovery | M0.2/M0.4 design before M0.3 | Distinguish credential versions from grant revisions; fenced success/failure publication; bounded orphan-session/revocation cleanup; crash/retry tests without blind OAuth replay | | Maximum stale-authority window | M0/P and M7 | Personal and corporation revalidation policy, scheduling budget, outage behavior and immediate local quarantine once changes are observed | | Rollout gates and dependency images | M0.1/P | Choose/test server-side capability/tenant/config gating; pin deployed production/admin images, including any optional dashboard | | Proxy/IP identity, JEV disclosure and paid-use policy | M0/P | Document trusted proxy chain; spoofed-header tests; provider/privacy disclosure; durable user/global budgets and no unrestricted anonymous paid inference | | Authenticated cache sharing | M1/M3/M7 | Default tenant/grant-context isolation for private locations/structures; separately approved sharing authority and revocation tests | | Finance backfill and incomplete-history semantics | M2 design | Source-specific windows/cursors, decimal-string IDs, deduplication, explicit gaps and no invented opening balances or lifetime profit | | Production hostname, environment and dev-data migration | P | Operator confirmation, separate secrets/data, safe encryption migration | | New ESI route scopes/roles/pagination/history | Before each adapter | Use the [verified planning matrix](research/expansion-data-contracts.md), capture pinned fixtures, and opt in to live checks; transaction/market-history retention and real corporation-role behavior remain unresolved | | Personal contracts/collateral and broader wealth coverage | After M2 core, before extending its completeness claims | Confirm product scope and research the additional routes/grants; keep unsupported positions explicitly excluded meanwhile | | Market venues, fee inputs and dynamic feed storage | M3 design | User-configured scenarios, verified fee/range semantics and ingestion benchmarks | | Industry modifiers, rounding and planner scale | M4/M5A | Current formula sources, worked examples, bounded-search benchmarks | | Capital/cyno/access facts ESI cannot supply | M6 design | Explicit manual/verified inputs and limitations; never invent docking or safety | | Corporation sharing/provider succession | M7 design | Permission matrix and revocation/transfer/failover tests | | Broader answer generation / external notifications | M8 design | Explicit provider/egress/privacy/budget approval | ## 17. Definition of done for every slice - Current source contract and migrations documented; implementations distinguish fixture, production and unavailable data. - One shared deterministic service with validated inputs, authorization, completeness and provenance. - Conventional UI plus typed assistant/manual fallback where applicable. - Unit/property tests for arithmetic and invariants; isolated integration, native-browser and adversarial tenant tests for changed boundaries. - Bounded resource use, safe errors, appropriate logs/metrics, retention/deletion behavior and rollback. - No real-user write smoke against the persistent deployment; consented live validation is recorded separately from mocks. - The server-side rollout/config gate implemented in M0 remains closed to other users until the slice's acceptance gate is met. It is a planned mechanism, not an existing feature. Public signup remains a separate, explicit operator decision.