feat: add dataset consent and primary character model
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
# T05 design record: dataset authorization and incremental consent
|
||||
|
||||
**Status:** local prototype implementation; not a production-readiness or public-launch approval.
|
||||
|
||||
## Primary decision
|
||||
|
||||
An application user has exactly one **primary** linked character. The primary is the only character that can authenticate the site while signed out. Additional linked characters are **data-only** and cannot authenticate signed out. While authenticated, the user can designate any currently active linked character as the primary; the old primary is demoted in the same Convex transaction.
|
||||
|
||||
The active authenticated application session is sufficient to link another character. The callback binds to that initiating session and revalidates it again in the persistence transaction. A character ID supplied by a browser is only a server-resolved selector. A verified owner continuity claim is per character and never groups EVE characters into an account.
|
||||
|
||||
## Consent and authority
|
||||
|
||||
- Capability definitions select required scopes. The application route combines those with only server-allowlisted scopes already granted to the selected linked character when upgrading/reconnecting.
|
||||
- OAuth state is one-time and records intent (`initial_login`, `link_character`, `upgrade_dataset`, or `reconnect`), capability, requested/preserved scopes, target character and initiating session hash.
|
||||
- The verified provider grant, not the requested scope list, is persisted as authority. Scalar and array `scp` claims are normalized by SSO verification. Reduced grants are accepted but block/invalidate affected datasets and remove old asset generations from reads.
|
||||
- Character records carry role, authorization status, grant revision, credential version and authorization epoch. Dataset statuses carry their own status and matching fences. Local cancellation revokes authority, clears active asset generations, removes credentials and quarantines character jobs where present.
|
||||
- Owner mismatch never transfers data. The old character is quarantined, credentials and active data access are fenced, and future jobs are quarantined. Full transfer-to-new-owner recovery is explicitly deferred.
|
||||
|
||||
Session replacement is performed transactionally with login persistence where possible: the initiating session is revoked as the new session is inserted. OAuth code consumption remains one-time, and callback failures never blindly replay a code.
|
||||
|
||||
## Prototype data policy and deferrals
|
||||
|
||||
This repository is pre-production and has no users beyond the operator's test character. Schema/model changes are development-only: when local data makes a change costly, wipe/reseed it rather than adding earliest-character migration, lazy-normalization or retention-compatibility machinery. The first linked character is created primary directly; no legacy migration workflow is implemented.
|
||||
|
||||
The local prototype keeps essential correctness/security boundaries: server-derived authorization, tenant isolation, scope allowlists, one-time OAuth, no token leakage, fail-closed owner checks, dataset/read fencing and safe fixed callback errors. It intentionally defers T01 production evidence and full lifecycle work: CI/deployed artifact proof, browser failure injection, restore/migration rollback rehearsals, retention/GC, public quotas/admission, production session/orphan recovery policy, remote revocation outbox, unlink/delete, and complete transfer recovery. T06 typed transport and T07 durable worker transport are not implemented here. Production migration, retention, rollback and public-launch gates remain mandatory after prototype approval and before P.
|
||||
+13
-11
@@ -2,9 +2,11 @@
|
||||
|
||||
**Status:** this document is the approved task plan. T01–T04 have since been worked in parallel; see [first-wave integration evidence](first-wave-verification.md) for implemented scope, checks and remaining gates. This plan itself does not authorize deployment or public signup.
|
||||
|
||||
**Prototype order:** the project is pre-production with no users beyond the operator's test character. Prioritize a functional disposable local prototype first: first login, authenticated linking, capability consent/upgrades, reduced-grant invalidation, primary switching, cancellation, sync/read fencing and tenant isolation. Defer CI/deployed-artifact proof, browser failure injection, restore/migration rollback rehearsals, retention/GC, public quotas/admission, production hardening and similar release evidence until the operator approves that prototype. Essential server-derived authorization, tenant isolation, scope allowlists, one-time OAuth, no token leakage and fail-closed ownership remain prototype requirements. Before public launch, wipe/reseed local data rather than add costly migration/retention compatibility; this exception ends at production, where migration/retention gates remain mandatory.
|
||||
|
||||
**Scope:** the seven work items in [roadmap §15](roadmap.md#15-first-implementation-batch-after-this-plan), split into independently reviewable tasks. The roadmap remains authoritative for security, correctness and definition of done. Later milestones and the remaining M0/public hardening stay in the backlog.
|
||||
|
||||
**Planning baseline:** `fdcc486` (`Initial Commit`). The roadmap records 97 passing tests; this planning pass did not rerun them. Reconfirm the baseline before implementation. Existing `jobs`, `userPreferences` and `referenceSyncMetadata` tables are placeholders, not services.
|
||||
**Planning baseline:** `fdcc486` (`Initial Commit`). The roadmap records an earlier 97-test gate; each prototype change reruns the current local suite. Existing `jobs`, `userPreferences` and `referenceSyncMetadata` tables are placeholders, not services.
|
||||
|
||||
## Execution model
|
||||
|
||||
@@ -13,7 +15,7 @@
|
||||
- Use one integration owner for shared-file patches. Each task supplies its own required schema/store/wiring changes and tests; the integration owner serializes those patches and reruns the combined suite. This is a role, not permission to postpone authorization until integration.
|
||||
- Prefer feature-local modules and tests over expanding central files. Proposed paths are implementation boundaries, not established APIs. Do not undertake a general architecture rewrite.
|
||||
- Ready tasks need not all run at once. Assign available agents to independent lanes; more worktrees do not remove dependency or shared-file constraints.
|
||||
- Every worktree uses synthetic users, isolated Convex state, separate ports/Compose project names, output directories and keys. Do not copy `.env.local`, production volumes, grants or live instance credentials. Never run existing live smoke scripts without reviewing their targets and obtaining consent.
|
||||
- Every worktree uses synthetic users, isolated Convex state, separate ports/Compose project names, output directories and keys. Do not copy `.env.local`, production volumes, grants or live instance credentials. Never run existing live smoke scripts without reviewing their targets and obtaining consent. Disposable local data may be wiped/reseeded after schema/auth changes; do not build prototype-only migration machinery.
|
||||
- No branch enables public signup, changes the current ingress gate, performs real-user write smoke tests, or commits secrets. New functionality stays behind the server-side gate from T01 until its acceptance criteria pass.
|
||||
|
||||
## Task graph and suggested waves
|
||||
@@ -39,12 +41,12 @@ Sizes describe scope, not time estimates. Split an L task further if its contrac
|
||||
|
||||
**Suggested schedule (dependency edges, not wave numbers, determine readiness):**
|
||||
|
||||
1. Start **T01 + T02 + T03 + T04** independently.
|
||||
2. Start **T05 + T06** once their inputs land. T03 can continue independently.
|
||||
3. Start **T07 + T08** once their inputs land. Serialize any ESI/application wiring overlap.
|
||||
4. Start **T09 + T13** once their inputs land: this is the inventory/finance split. Wallet balances do not wait for inventory queries.
|
||||
5. Start **T10 + T11 + T12** once T09 lands; T13 can continue alongside them.
|
||||
6. Run **T14** on the merged result. Passing it permits only the agreed private slice, not public beta or a complete wealth claim.
|
||||
1. **Local prototype wave:** land the minimum T01/T02 contracts and gates needed for T05, then prioritize **T05 + T06** and the existing local asset flow. T03/T04 can continue independently where they unblock functionality.
|
||||
2. Start **T07 + T08** once their inputs land. Serialize any ESI/application wiring overlap; do not expand into production worker/restore evidence yet.
|
||||
3. Start **T09 + T13** once their inputs land: this is the inventory/finance split. Wallet balances do not wait for inventory queries.
|
||||
4. Start **T10 + T11 + T12** once T09 lands; T13 can continue alongside them.
|
||||
5. **Prototype approval gate:** operator reviews functional local flows and decides whether to invest in operations/release evidence.
|
||||
6. **Post-approval production wave:** run T01's deferred CI/deployed proof, browser failure injection, backup/restore/migration rollback, retention/GC, quotas/admission and hardening, then run T14 on the approved merged result. Passing prototype tests alone never permits public beta.
|
||||
|
||||
## Shared-file ownership and merge discipline
|
||||
|
||||
@@ -108,11 +110,11 @@ Also freeze the first inventory query/result/filter/cursor contract, reference/l
|
||||
|
||||
**Own:** SSO/security/auth routes, dataset capability gates, character management status/actions, initial schema/store/status changes and dedicated auth tests.
|
||||
|
||||
**Deliver:** persisted dataset status and grant revisions; server-allowlisted capability scopes; one-time OAuth binding to requested scopes, operation/link intent and initiating session; verified actual grants; deliberate preservation of required existing scopes. Support upgrade/reconnect, reduced/denied grants, local dataset cancellation/invalidation and visible missing requirements.
|
||||
**Deliver:** persisted per-dataset status, a single primary login role plus data-only linked roles, grant revisions and credential/authorization epochs; server-allowlisted capability scopes; one-time OAuth binding to requested scopes, operation/link intent and initiating session; verified actual grants; deliberate preservation of required existing scopes. Support upgrade/reconnect, reduced/denied grants, authenticated primary switching, local dataset cancellation/invalidation and visible missing requirements. Keep wallet behind its release capability.
|
||||
|
||||
Implement the identity enforcement needed by the new pipeline: revalidate linking authority at persistence, trusted-character step-up for credential additions, local transfer/revocation quarantine and job/cache invalidation. Callback persistence/session replacement must be atomic where possible or explicitly compensating with bounded orphan cleanup. Uncertain consumed-code outcomes require recovery, not blind replay. Full unlink/delete/session-management UX remains later M0 work.
|
||||
Implement the prototype identity enforcement needed by the pipeline: revalidate linking authority at persistence, local owner/revocation quarantine and job/cache invalidation, and atomic session replacement where practical. Never replay a consumed OAuth code; full transfer-to-new-owner recovery, unlink/delete/session-management UX and production orphan/retention policy remain deferred.
|
||||
|
||||
**Done:** scalar/array scopes, stale link sessions, same-character reauth, distinct owner bindings, reduced grants, persistence/cookie-delivery failures and borrowed selectors pass isolated tests. Transfer cannot expose prior-user data; quarantined credentials cannot service reads or future jobs. Schema migration is backward compatible and legacy missing state fails conservatively.
|
||||
**Done:** scalar/array scopes, stale link sessions, primary-character reauthentication, signed-out data-only rejection, distinct owner bindings, reduced grants, primary switching, cancellation and borrowed selectors pass isolated tests. Transfer cannot expose prior-user data; quarantined credentials cannot service reads or future jobs. This pre-production branch may wipe/reseed local data instead of implementing legacy migrations/lazy normalization; production migration/retention gates remain required before P.
|
||||
|
||||
### T06 — Typed ESI transport extensions
|
||||
|
||||
|
||||
+27
-17
@@ -1,17 +1,18 @@
|
||||
# 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.
|
||||
**Baseline:** the operator has verified real EVE sign-in, asset synchronization, and matching Assets/chat reference valuations. The earlier implementation gate recorded 97 passing tests; local prototype checks are rerun as features land.
|
||||
**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.
|
||||
2. **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.
|
||||
3. **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.
|
||||
4. **Eventually support open public signup**, not just a private installation. Public signup does not make anybody's character data public.
|
||||
5. **Include corporation features later**, behind a separate authorization/sharing design.
|
||||
6. 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.
|
||||
7. 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.
|
||||
|
||||
@@ -19,7 +20,7 @@ New service/table/path names below are proposed implementation boundaries, not e
|
||||
|
||||
| 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 |
|
||||
| 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 |
|
||||
@@ -34,6 +35,14 @@ New service/table/path names below are proposed implementation boundaries, not e
|
||||
|
||||
## 3. Recommended delivery order
|
||||
|
||||
### Local-prototype phase (before production-readiness work)
|
||||
|
||||
1. **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.
|
||||
2. **Prototype approval:** the operator decides that the local flows are useful and stable enough to justify operational investment.
|
||||
3. **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 |
|
||||
@@ -98,12 +107,12 @@ Keep valuation methods distinct. Never quietly replace an average price with an
|
||||
|
||||
### 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. T01 provides an approved deployment configuration/capability allowlist with tests; it protects current routes, assistant dispatch, sync entry points and subscriptions. Durable jobs and any new capability still require their own reviewed entry points. Gates must protect server behavior, not merely hide UI controls.
|
||||
**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.
|
||||
@@ -122,11 +131,12 @@ Keep valuation methods distinct. Never quietly replace an average price with an
|
||||
- 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.
|
||||
- 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 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.
|
||||
- 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.
|
||||
|
||||
@@ -317,7 +327,7 @@ Keep the initial branch focused; do not start every milestone at once. See the [
|
||||
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
||||
@@ -52,6 +52,6 @@ Audit regressions cover native-form header/CSRF boundaries, shared artifact-dire
|
||||
- Broad TypeSafe inference quality or the proposed 0.80 confidence threshold's calibration on EVE requests.
|
||||
- Compatibility with arbitrary future archive releases, station-data coverage, large-scale memory/performance benchmarks, or production-size market analytics.
|
||||
- End-to-end browser automation/visual accessibility audit; the web smoke verifies the built server and endpoints, not all browser interactions.
|
||||
- A comprehensive TLS/proxy security audit, backup/restore drills, rotation/recovery, unlink/revocation UX, retention/GC, or multi-process refresh/job recovery.
|
||||
- A comprehensive TLS/proxy security audit, backup/restore drills, rotation/recovery, remote revocation and full unlink/delete lifecycle, retention/GC, or multi-process refresh/job recovery. T05 adds local data-only-character cancellation only.
|
||||
|
||||
These remain explicit deployment/incremental-development gates, not silent success assumptions.
|
||||
|
||||
Reference in New Issue
Block a user