Skip to content

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, ShipConstructionProject are 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: - ownerPlayer (many-to-many via player_stations). - sectorSector (FK sector_uuid — see ./galaxy.md#sector). - marketMarket (1:1, cascade delete) — see ./economy.md. - regionRegion (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)