Stations & TradeDocks — Schema¶
Status: 🚧 Partial — Station core (CLASS_0-11, commodities, services, defenses) is committed; station-protection tier (security/tractor/deny-list/fee-distribution), syndicate fence flag … (impl audit 2026-06-16)
Trade hubs in sectors. Station covers the canonical Class-0…Class-11 stations (player-ownable, faction-affiliated). TradeDock is the premium NPC-only shipyard hub with its own slip-rental construction pipeline. Companion docs: ../FEATURES/economy/trading.md, ../FEATURES/economy/port-ownership.md, ../FEATURES/economy/tradedock-shipyard.md.
Schema status¶
Per ADR-0066 D-V1, schema-level implementation status is consolidated here. Field descriptions describe the target schema.
Design-only columns — present in the spec, not yet committed:
Station:security,security_level,defense_budget,tractor_strength,wanted_threshold,deny_list_player_ids,fee_distribution,has_syndicate_fence,is_tradedock,tradedock_tier,region_assignment_role,defense_state.TradeDock,ConstructionSlip,ShipConstructionProjectare entire models that are design-only — the source paths target files that do not yet exist.
All other columns on this page are committed.
Station¶
Source: services/gameserver/src/models/station.py
Purpose: Trade/service hub in a sector; also the locus for the haggling AI and player-acquirable ownership.
Fields:
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| name | String(100) | not null | |
| sector_id | Integer | not null | |
| sector_uuid | UUID FK sectors.id | nullable, CASCADE | |
| owner_id | UUID | nullable | many-to-many via player_stations |
| station_class | Enum station_class |
not null | CLASS_0…CLASS_11; encodes trading pattern (mining/agri/industrial/distribution/collection/black-hole/nova/luxury/etc.) |
| type | Enum station_type |
not null | TRADING/MILITARY/INDUSTRIAL/MINING/SCIENTIFIC/SHIPYARD/OUTPOST/BLACK_MARKET/DIPLOMATIC/CORPORATE |
| status | Enum station_status |
default OPERATIONAL | OPERATIONAL/DAMAGED/UNDER_CONSTRUCTION/UNDER_ATTACK/LOCKDOWN/ABANDONED/RESTRICTED |
| size | Integer | default 5 | 1-10 |
| faction_affiliation | String | nullable | |
| trade_volume | Integer | default 100 | |
| market_volatility | Integer | default 50 | 0-100 |
| commodities | JSONB | not null | per-commodity (ore/organics/equipment/fuel/luxury_goods/gourmet_food/exotic_technology/colonists) blob with quantity, capacity, base_price, current_price, production_rate, price_variance, buys, sells |
| trader_personality | JSONB | not null | type, haggling_difficulty, preferred_appeal_types, memory_duration, trust_level, quirks |
| price_modifiers | JSONB | default {} | |
| services | JSONB | not null | ship_dealer, ship_repair, ship_maintenance, ship_upgrades, insurance, drone_shop, genesis_dealer, mine_dealer, diplomatic_services, storage_rental, market_intelligence, refining_facility, luxury_amenities |
| service_prices | JSONB | default {} | |
| defenses | JSONB | not null | defense_drones, max_defense_drones, auto_turrets, defense_grid, shield_strength, patrol_ships, military_contract — siege defense + outward sector security per ../FEATURES/economy/port-ownership.md. |
| security | JSONB | default {} |
Inward docked-ship protection: {tier, defense_drones_active, defense_drones_max, guard_npc_ids, guard_captain_npc_id, barracks_id, tractor_lock_active, tractor_locked_ship_id, tractor_locked_at, last_attack_at, last_tractor_event_at}. Distinct from defenses — see ../FEATURES/economy/station-protection.md. |
| security_level | Enum station_security_tier |
default none |
none / basic / standard / premium. Drives docked-ship protection guarantees, anti-theft tractor strength, hired-guard count, and per-dock fee multiplier. |
| defense_budget | Integer | default 0 | Credits in the station's defense fund; daily upkeep ticks consume it; runs negative for 7 days → station auto-downgrades to none. |
| tractor_strength | Enum tractor_strength |
default none |
none / weak / strong / immobilizing. Derived from security_level but stored for fast read. Reads on every undock attempt; activates on stolen-ship / wanted-pilot / deny-listed pilot. |
| wanted_threshold | Integer | default -500 |
Personal-rep cutoff for tractor activation on wanted pilots. Owner-tunable. |
| deny_list_player_ids | JSONB | default [] |
Owner-set blocklist of player UUIDs barred from undocking. |
| fee_distribution | JSONB | default {"defense_pct": 0.4, "owner_pct": 0.3, "operating_pct": 0.3} |
Docking-fee revenue split: 40% defense fund / 30% owner / 30% operating. Owner-tunable within bounds (defense 30-60%, owner 10-50%, operating fixed at 30%). |
| ownership | JSONB | nullable | player ownership details when claimed |
| last_market_update | DateTime | server default now | |
| market_update_frequency | Integer | default 6 | hours |
| reputation_threshold | Integer | default 0 | min reputation to dock |
| is_quest_hub, is_faction_headquarters, is_player_ownable | Boolean | defaults false/false/true | |
| acquisition_requirements | JSONB | not null | min_trade_volume, min_faction_standing, base_price |
| last_attacked | DateTime | nullable | |
| is_destroyed | Boolean | default false | |
| recovery_time | DateTime | nullable | |
| active_events | JSONB | default [] | |
| special_services | ARRAY(String) | default [] | |
| region_id | UUID FK regions.id | nullable | |
| has_syndicate_fence | Boolean | default false | — set at galaxy generation on ~8% of eligible non-Federation, non-Nova, non-TradeDock stations; gates the embedded Shadow Syndicate fence sub-port. See ../FEATURES/economy/black-market.md#syndicate-fence-venues. |
| is_tradedock | Boolean | default false | Per ADR-0041 (and confirmed in ADR-0065 R-D1). True for the dedicated TradeDocks per region (Frontier-zone trade-anchor pair). Note this is distinct from the standalone TradeDock model below — the column flags Stations that operate as TradeDocks within the Station table for unified queries. |
| tradedock_tier | Enum nullable | default NULL | Per ADR-0041. gateway / industrial / luxury per the per-tier specialization table. Null when is_tradedock = false. |
| region_assignment_role | Enum nullable | default NULL | Per ADR-0041. welcome / frontier_anchor / tradedock_a / tradedock_b per the per-region station-role table. Null for procedural stations without a designated role. |
| defense_state | JSONB | nullable | Per ADR-0065 M-J2. Anchored shape: {current_strength: float 0..1, last_damage_at: iso8601 | null, last_recovery_tick_at: iso8601, armor_layer_intact: bool, shield_layer_intact: bool, weapon_systems_online: bool}. current_strength = 1.0 is full defense; 0.0 is stripped. Used by the pirate-holding-raid recovery path (see ../SYSTEMS/pirate-holding-raid.md). |
Relationships:
- owner → Player (many-to-many via player_stations).
- sector → Sector (FK sector_uuid — see ./galaxy.md#sector).
- market → Market (1:1, cascade delete) — see ./economy.md.
- region → Region (see ./galaxy.md#region).
player_stations (association)¶
Columns: player_id, station_id (composite PK), acquired_at.
TradeDock¶
Source: services/gameserver/src/models/tradedock.py (target — does not exist)
Purpose: Premium trading hub plus 12-slip shipyard. Distinct from Station because TradeDocks are NPC-owned, can't be captured/destroyed, run a slip-rental shipyard, and have their own rare-commodity inventory layer. See ../FEATURES/economy/tradedock-shipyard.md.
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| name | String(100) | not null | |
| sector_id | UUID FK sectors.id | not null, CASCADE | |
| region_id | UUID FK regions.id | not null | |
| controlling_faction | String(50) | not null | Federation / Mercantile / Frontier / etc. |
| station_class_equivalent | Integer | default 11 | reputation-and-defense-equivalent class for service availability |
| total_slips | Integer | default 12 | |
| occupied_slips | Integer | default 0 | denormalized count |
| rare_commodity_inventory | JSONB | not null | per-rare-commodity stock (titanium_alloys, lumen_crystals, quantum_shards, etc.) |
| premium_spread_bonus | Float | default 0.125 | 10–15% better-than-base spread (±0.025) |
| transaction_fee_pct | Float | default 0.0 | TradeDocks waive transaction fees |
| bulk_discount_per_1k | Float | default 0.05 | 5% per 1,000-unit purchase, 20% cap |
| reputation_gate | Integer | default 200 | minimum faction reputation to enter slip queue |
| guest_fee | Integer | default 100000 | one-time fee for cross-faction guests |
| is_destroyed | Boolean | default false | always false — TradeDocks can't be destroyed; column reserved |
| region_funded | Boolean | default false | true if built by a player-region (5% income to region treasury) |
| created_at, updated_at | DateTime | server defaults |
Relationships: sector, region, slips (1:many → ConstructionSlip), controlling_faction_obj (FK to Faction)
ConstructionSlip¶
Source: services/gameserver/src/models/construction_slip.py (target)
Purpose: One of 12 shipbuilding slips at a TradeDock. Holds an in-progress ShipConstructionProject while it builds.
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| tradedock_id | UUID FK tradedocks.id | not null, CASCADE | |
| slip_number | Integer | not null | 1–12 within the TradeDock |
| status | Enum slip_status |
default available |
available / reserved / building / claim_pending / abandoned |
| current_project_id | UUID FK ship_construction_projects.id | nullable | active project occupying the slip |
| reserved_until | DateTime | nullable | reservation expiry for reserved status (24h hold) |
| reserved_by | UUID FK players.id | nullable |
Relationships: tradedock, current_project (1:1 to active ShipConstructionProject), reserver (Player)
ShipConstructionProject¶
Source: services/gameserver/src/models/ship_construction_project.py (target)
Purpose: A player's ship-build project running on a slip. Tracks construction phase, milestone payments, and customization.
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| slip_id | UUID FK construction_slips.id | not null | |
| player_id | UUID FK players.id | not null | builder |
| target_ship_type | Enum ship_type |
not null | Scout / Light Freighter / Fast Courier / Cargo Hauler / Defender / Colony Ship / Carrier / Warp Jumper (8 craft-able types — Escape Pod is issued, not slip-built) |
| construction_phase | Enum construction_phase |
default frame |
frame / systems / outfitting / final |
| progress_pct | Float | default 0.0 | 0.0–1.0 across all phases |
| started_at | DateTime | server default | |
| target_completion_at | DateTime | not null | start + planned build days |
| total_project_cost | Integer | not null | all-in cost (slip + labour + resources at market) |
| credits_paid | Integer | default 0 | cumulative milestone payments received |
| deposit_paid | Boolean | default false | initial 10–25% deposit |
| keel_milestone_paid | Boolean | default false | first 25% milestone |
| hull_milestone_paid | Boolean | default false | second 25% milestone |
| final_payment_paid | Boolean | default false | final 25–40% on claim |
| resources_delivered | JSONB | default {} |
per-resource delivery counters |
| resources_required | JSONB | not null | resource bundle for the target ship |
| customization | JSONB | default {} |
paint scheme, name, optional modifications |
| space_engineer_assigned | UUID FK players.id | nullable | profession-bonus assignee |
| event_log | JSONB | default [] |
construction events (Quality Discovery / Resource Shortage / etc.) |
| status | Enum project_status |
default building |
building / paused (rent overdue) / cancelled / complete / claimed |
Relationships: slip, player, space_engineer (Player)