49 KiB
Implementation roadmap
Status: planning proposal, not implementation or a public-launch declaration.
Baseline: prior checkpoints historically recorded live sign-in, asset synchronization and matching Assets/chat reference valuations for one character (see verification); that history is not new T07 evidence. This T07 checkpoint records a local, disposable prototype only, with no new deployed/live ESI or production-readiness claim. T07 durable synchronization is implemented and verified locally with the current 204-test suite. T08 location/containment enrichment remains a separate feature whose post-assets/pre-publication integration is still pending.
Evidence: architecture, milestone 1, verification, ESI research, expansion data/permission matrix, and reference operations.
1. Decisions confirmed for this roadmap
- Inventory and personal finances deliver the next user-visible value.
- Work locally first. The project is pre-production and currently has no users beyond the operator's test character. Functional local flows are the next gate; production-readiness evidence is deliberately deferred until the operator approves the prototype. Before public launch, wiping/reseeding development data is preferred over adding costly migration/retention compatibility. This exception ends at production/public launch: production migration, retention and rollback gates remain mandatory before P.
- Keep EVE-only sign-in. One linked character is the sole primary/site-login character. Additional linked characters are data-only and cannot authenticate signed out; an authenticated user may switch the sole primary. An owner hash is never an EVE-account grouping key.
- Eventually support open public signup, not just a private installation. Public signup does not make anybody's character data public.
- Include corporation features later, behind a separate authorization/sharing design.
- 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.
- 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.
T07 prototype checkpoint
T07 is implemented as a local prototype, not a deployment claim. It requires the distinct CONVEX_SYNC_WORKER_SECRET in Convex and the worker environment, alongside TOKEN_ENCRYPTION_KEY, EVE client credentials and ESI_USER_AGENT. Start Compose workers only through the explicit worker profile; standalone development uses a worker-only .env.worker. T08 core modules and their integration at the post-assets/pre-publication seam remain pending.
2. What exists versus what still needs building
| Area | Current implementation | Important gap |
|---|---|---|
| Identity | Verified EVE SSO/PKCE, encrypted grants, one primary login character, data-only linked characters, authenticated primary switching, opaque sessions, app JWTs | Recovery, unlink/delete, transfer lifecycle, production 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 | T07 durable queued jobs, dedicated worker, leases, fenced generation publication, cancellation/recovery and shared refresh coordination | T08 enrichment integration and production release evidence remain pending |
| 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
Local-prototype phase (before production-readiness work)
- Functional local prototype: implement and exercise first login, authenticated linking, capability-selected consent/upgrades, reduced-grant invalidation, primary switching, cancellation, asset sync/read fencing and tenant isolation using disposable Convex data.
- Prototype approval: the operator decides that the local flows are useful and stable enough to justify operational investment.
- Production-readiness phase: only after approval, add CI/deployed-artifact proof, browser failure injection, restore/migration rollback rehearsals, retention/GC, public quotas/admission, lifecycle recovery, and other P/release evidence.
Essential correctness and security boundaries remain in the prototype: server-derived authorization, tenant isolation, scope allowlists, one-time OAuth, no token leakage, fail-closed owner checks and no blind OAuth-code replay. Prototype work must not grow production operational machinery prematurely.
| 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 — Local prototype baseline (production evidence deferred)
- Review essential secret exclusions and establish an operator-approved local baseline; no commit is performed by this planning work.
- Run local tests/typecheck/build as useful feedback, but defer CI, deployed-artifact proof, browser failure injection, migration/rollback rehearsal and public launch evidence until prototype approval.
- Exercise native forms, OAuth redirect/cookie paths, singleton/array scopes, linking, primary switching, cancellation, tenant isolation and pending-request behavior with disposable synthetic/local data.
- Because there are no production users, wipe/reseed local data when schema/auth changes make migration compatibility costly; do not add legacy migration/lazy-normalization machinery for prototype-only rows.
- Keep server-side rollout gating and essential auth boundaries. Durable jobs and any new capability still require their own reviewed entry points later.
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
jobsrather than adding more long-running work toPOST /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 the first linked character as the sole login/primary credential under the existing model. Additional linked characters are data-only and cannot authenticate signed out; while authenticated, the user can designate another authorized linked character as the sole primary and the old primary is immediately demoted. Explain that anybody able to authenticate as the primary can access the application account: linking is not merely read-only data sharing.
- During the local prototype, test owner/revocation/cancellation fencing and primary switching. Full recovery, transfer, unlink/delete and production lifecycle evidence remain deferred until prototype approval.
- During the local prototype, an active authenticated application session is sufficient to link a data-only character or switch the primary. Revisit fresh proof for sensitive account actions, session listing/revocation, host-bound cookie naming and sibling-subdomain session-fixation tests during the post-prototype production-readiness phase.
- 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 the current primary character restores the same application account; a data-only linked character cannot authenticate while signed out. Users must first sign into the account before linking a new alt. A signed-out login with an unlinked character can create a separate application account; matching owner claims must not merge them. For this pre-production prototype, reset/reseed disposable data instead of implementing an earliest-character migration or compatibility workflow. Production migration and accidental-duplicate handling remain launch gates.
- 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
- 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.
- 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_singletonasisSingleton, 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. - 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.
- 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.
- 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. - Limited history: snapshot differences and retained summary checkpoints, labelled as observations rather than inferred trades. Do not fabricate history predating collection.
- 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_idand 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,000metre 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
CapitalRouterresult 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 for first-batch task briefs, dependencies, file ownership and merge order.
| Work item | Concrete output | Proof of completion |
|---|---|---|
| 1. Local prototype baseline | Local test/check/build feedback and disposable isolated fixtures | Current tests remain green; production deploy/restore/migration evidence waits for prototype approval |
| 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, 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 T01 remains closed to other users until the slice's acceptance gate is met. It is an operator-controlled mechanism, not a public-signup decision. Public signup remains separate and explicitly gated.