Skip to content

Factions & Teams

Status: 🚧 Partial — faction reputation and team structures partially shipped; trade pricing consumes team aggregate standing via get_trade_modifier on tip 46bce720 / #752; ✅ port-access dock reputation gate consumes team standing via resolve_effective_faction_standing_value on tip 46bce720 / #753 (LEG-814) — 🚧 mission-gate consumer remains tip-pending (Soft-HOLD #1305). (re-verified 2026-08-21 vs Sectorwars2102 46bce720.)

Two distinct social structures sometimes confused with each other:

  • Faction — an NPC organization. You build standing with it through emergent behavior — combat, trade, exploration, social acts, resource flows; you do not "join" a faction and there are no quests to accept. Affects pricing, port access, patrol response, territorial reception.
  • Team — a cooperative alliance of player accounts. You explicitly create or are invited to one; affects shared resources, coordinated combat, and treasury access.

A player has standing with every NPC faction simultaneously and is a member of at most one team.


Factions (NPC)

The seven designed factions

Faction Type Theme
Terran Federation Lawful Government Order, security, prosperity
Mercantile Guild Trade Consortium Profit-neutral, infrastructure-heavy
Frontier Coalition Independent Colonies Anti-Federation autonomy
Astral Mining Consortium Resource Corp Monopolistic mining
Nova Scientific Institute Research Org Quantum / exotic tech focus
Fringe Alliance Outlaw Coalition Frontier rebels, smuggler refuge
Shadow Syndicate Criminal Syndicate Organized black-market trade
Galactic Concord Operator-managed Authority (📐) Central Nexus governance — fields the Nexus Sentinel Corps

Two hostile-only entities — Pirates (random NPC raiders) and The Cabal (📐 Design-only endgame antagonist with a single fixed Headquarters in Terran Space) — cannot be allied with; only attacked. See ./faction-lore.md for full lore on all nine.

The Federation Police (Terran Federation enforcement arm — Marshal Interdictor squads in Federation Zones) and the Nexus Sentinel Corps (Galactic Concord enforcement arm in the Central Nexus) are both NPC-only police forces with special-issue Interdictor hulls (Federation Marshal Interdictor and Nexus Sentinel Interdictor respectively). They have their own engagement triggers, jurisdiction boundaries, and rep penalties for attacking. Full design in ./police-forces.md.

Reputation scale

Per-faction reputation runs −800 to +800, stored on Reputation.current_value. Two related views over the value coexist:

  • The 17-tier ReputationLevel enum (models/reputation.py) — sets Reputation.current_level, the display title, and the value used by combat-response and port-access rules.
  • The 9 trade-modifier buckets (faction_service.py:TRADE_MODIFIERS) — set the price multiplier at faction-controlled ports. Each bucket coarse-grains one or more enum tiers.

Both are derived from the same numeric value; the table below shows the boundaries and the price effect that applies in each band.

Reputation value Level enum Trade-modifier bucket Price multiplier
≥ +700 EXALTED EXALTED ×0.85 (15% discount)
+500 to +699 REVERED (+700) / HONORED (+500) REVERED ×0.90
+300 to +499 VALUED (+400) / RESPECTED (+300) HONORED ×0.95
+100 to +299 TRUSTED (+200) / ACKNOWLEDGED (+100) FRIENDLY ×0.97
+50 to +99 RECOGNIZED NEUTRAL ×1.00
−50 to +49 NEUTRAL NEUTRAL ×1.00
−51 to −99 NEUTRAL (no enum boundary here) NEUTRAL ×1.00
−100 to −299 QUESTIONABLE (−100) / SUSPICIOUS (−200) / UNTRUSTWORTHY (−300) UNFRIENDLY ×1.05
−300 to −499 SMUGGLER (−400) HOSTILE ×1.15
−500 to −699 PIRATE (−500) / OUTLAW (−600) HATED ×1.30
≤ −700 CRIMINAL (−700) / PUBLIC ENEMY (below) PUBLIC ENEMY ×1.50

The exact threshold function is faction_service.py:_calculate_reputation_level for the enum and TRADE_MODIFIERS (high-to-low list) for the modifier bucket.

Reputation triggers

Faction reputation is emergent only. There are no missions or quests to accept; rep moves through six trigger surfaces — combat, trade, exploration, social/political, ongoing-state drips, and resource flows — driven by natural play. The full set is canonical per ADR-0032.

Triggers are dispatched server-side through a single apply_emergent_action(player, action_type, sector_id, witnesses) wrapper that fans out to per-faction update_reputation calls in one transaction, applies the rivalry-cascade rule (below), and clamps results against the F2 decay ±100 floor/ceiling and combined-rep caps.

✅ Shipped — the apply_emergent_action(db, player, action, context) dispatcher (services/gameserver/src/services/emergent_reputation_service.py): a canon trigger table, fan-out via faction_service.apply_faction_rep_delta, and the rivalry cascade. Live call sites currently wire five triggers:

  1. Kill a Pirate or Cabal NPC → +5 Federationcombat_service kill resolver (KILL_PIRATE_NPC / KILL_CABAL_NPC; Cabal NPC spawn itself remains 📐 Design-only)
  2. Buy BASIC / STANDARD / PREMIUM insurance → +2 / +5 / +10 Mercantile Guild — once per hull at ship_upgrades insurance purchase (BUY_INSURANCE_*)
  3. First-scan a NEBULA or BLACK_HOLE sector → +15 Nova Scientific Institutemovement_service first-visit (NOVA_FIRST_SCAN_RESEARCH_SECTOR; ANOMALY / WARP_STORM still unrepresentable — no Sector.type value)
  4. Harvest Quantum Shards in a nebula → +1 Nova per 3 Shardsquantum_service harvest (HARVEST_NEBULA_SHARDS_NS)
  5. Build a public toll warp gate → Mercantile +30 / Frontier +5 / Nova +5warp_gate_service gate activation (BUILD_PUBLIC_WARP_GATE)

Remaining triggers below stay 📐 Design-only until their call sites invoke the dispatcher.

Per-faction trigger tables

Terran Federation (lawful order)

Action Δ Notes
Kill a Pirate or Cabal NPC +5 combat resolver post-hook — ✅ Shipped (combat_service via KILL_PIRATE_NPC / KILL_CABAL_NPC); Cabal NPC spawn itself remains 📐 Design-only
Kill a player with active Wanted/Suspect status in Fed-Controlled space +15 combat hook reads wanted_status
Kill a system-bounty target in fedspace +25 bounty payout post-hook
Trade at a Federation-flagged port +1 / 5,000 cr re-tuned from +1/10,000
Defend a Fed-Controlled sector (drone defense survives an attack) +20 re-tuned from +15
Discover a sector inside or adjacent to Fed territory +10 re-tuned from +5
Pay region tax cumulatively +1 / 25,000 cr taxed regional governance hook
Repel a planet siege on Fed-aligned colony +50 siege-lift event
Use the Federation distress beacon (one-way-stranding rescue) −10 / use 24-hour cooldown; free transport to nearest fedspace sector. The panic-button cost for being trapped behind a one-way warp. See ../galaxy/sectors.md#one-way-warps.

Mercantile Guild (profit-neutral infrastructure)

Action Δ Notes
Trade at any Guild-flagged station +1 / 5,000 cr core loop
Use a player toll gate (someone else's public gate, with cargo) +1 / 5,000 cr cargo value rewards trade-network participation
Successful arbitrage round-trip (≥30k profit, ≥3 sectors apart) +5 rewards skill, not just volume
Buy STANDARD insurance +5 one-time per hull — ✅ Shipped (ship_upgrades via BUY_INSURANCE_STANDARD)
Buy PREMIUM insurance +10 one-time per hull — ✅ Shipped (ship_upgrades via BUY_INSURANCE_PREMIUM)
Buy BASIC insurance +2 one-time per hull — ✅ Shipped (ship_upgrades via BUY_INSURANCE_BASIC)
Honor a public market-make order (post + fill within 24h) +5 reliability signal
Operate player port at fair tariff (5–6%) for 30 days +20/month per ../economy/port-ownership.md; legal fair band = tip MIN_TAX_RATE..FAIR_TARIFF_MAX (0.05..0.06)

Frontier Coalition (anti-Federation autonomy)

Action Δ Notes
Discover a sector ≥10 hops from any Capital +15 exploration core
First-arrival in an isolated cluster via Quantum Jump +30 trailblazer signal
Establish a colony in a Frontier-zone sector +50 their core mission
Tow a non-team-mate's drifting/escape-pod ship across ≥2 sectors +15 good-neighbor emergent
Trade at a Frontier outpost +1 / 5,000 cr volume
Sell gourmet_food or luxury_goods to a Frontier colony port +2 / 10,000 cr luxury-starved colonies
Defend a Frontier sector from pirates +20 defense
Vote in a Frontier-aligned regional governance resolution +2 / vote civic participation
Harvest in a nebula adjacent to AM-influence sector without an AM license +5 / harvest contested extraction; pairs with the AM penalty above — see ../galaxy/quantum-resources.md#faction-reputation-hooks

Astral Mining Consortium (monopolistic mining — see ../economy/mining.md)

Action Δ Notes
Sell raw ore to an AM-flagged refinery +2 / 5,000 cr double-weighted
Mine an asteroid-field sector with Mining Laser equipped +1 / harvest cycle per ../economy/mining.md
Pay AM claim-license fee voluntarily +15 / license legitimizes extraction
Defend an AM-claimed sector during siege +25 core archetype
Trade precious_metals (Astral specialty) +1 / 8,000 cr specialty preference
Harvest in a nebula adjacent to AM-influence sector without an AM license −5 / harvest unlicensed extraction; pairs with FC entry below — see ../galaxy/quantum-resources.md#faction-reputation-hooks

Nova Scientific Institute (research)

Action Δ Notes
First-scan a NEBULA / BLACK_HOLE / ANOMALY / WARP_STORM sector +15 research data — ✅ Shipped for NEBULA / BLACK_HOLE (movement_service first-visit via NOVA_FIRST_SCAN_RESEARCH_SECTOR); ANOMALY / WARP_STORM unrepresentable (no Sector.type)
Harvest Quantum Shards in a nebula +1 / 3 Shards per ../galaxy/quantum-resources.md — ✅ Shipped (quantum_service harvest via HARVEST_NEBULA_SHARDS_NS)
Harvest Quantum Shards in a Crimson nebula specifically +1 / Shard 4× rate; Nova prizes high-field-strength data — 📐 Design-only (no distinct call site; general harvest uses the +1/3 path)
Refine 5 Shards → 1 Crystal at a Nova-flagged station +8 / job highest of the refining venues
Sell exotic_technology to a Nova-flagged station +2 / 5,000 cr research material
Run a long-range Quantum Jump scan (paid scan, 5 turns) +1 / scan, capped 5/day their tech, their data
Donate xeno-artifact to Nova station +30 one-shot rare event
Sell anomaly-investigation dataset to Nova +5 / dataset data is a commodity
First-scan a Genesis-formed planet within 7 days of formation +15 Genesis biology

Fringe Alliance (smuggler coalition)

Action Δ Notes
Black-market transaction at a Fringe-controlled port +25 / transaction per ../economy/black-market.md
Successfully evade a Federation contraband scan with cargo +10 / evasion anti-symmetric to Fed's scan-survive trigger
Trade at a Fringe-controlled port (legal goods) +1 / 5,000 cr volume
Pilot a stolen ship into Fringe space and dock at a Fringe port +5 one-shot per stolen-ship session
Survive a Suspect Status cycle (1+ hour) +15 one-shot per cycle
Tow a Fringe-flagged smuggler out of Fed pursuit +20 rescue mechanic
Pay tribute to a Pirate (the "pay" branch of the encounter) +2 refusing to fight is its own statement

Shadow Syndicate (criminal trade — see ../economy/black-market.md#syndicate-fence-venues)

Action Δ Notes
Fence a Cargo Wreck cargo at a Syndicate fence venue +5 / 5,000 cr fenced core loop
Sell stolen-flagged commodity (origin = early-grace salvage) +10 / transaction flagged-origin path
Launder credits through ≥3 trade hops (laundering chain completes) +20 / laundering completion per black-market spec
Survive a full Wanted Status cycle without impound +10 one-shot per Wanted cycle
Forge port-tariff records (skim ≥1% as port owner) +20 / month tariff-evasion event
Place player-bounty on Heroic+ player (frame-job) +10 / placement reads target's personal-rep tier

Pirates (hostile-only — capped at 0)

Action Δ Pirates Notes
Pay tribute to a Pirate +2 (toward 0) unchanged from canon
Spare a Pirate at <25% hull (let them flee) +5 (toward 0) mercy path
Sell to a Class-8 (Black Hole) port — pirate fence chain +1 / 5,000 cr (toward 0) economic engagement clambers out of deep negative

Negative emergent triggers (selection)

Action Affected Δ
Attack a faction-flagged ship host faction −50
Attack a faction-controlled port host faction −100
Smuggling violation in faction-policed sector policed faction −25
Hold a black-market commodity passing through Fed Core (drip) Federation −10 / sector hop
Mine in Astral-claimed sector unlicensed Astral −10 / extraction
Detonate Genesis Device in NEBULA sector Nova −50
Genesis-deploy in Federation core without permit Federation −100
Turn in a Fringe operative for bounty Fringe −100 + permanent betrayal flag
Sustained Heroic personal rep (≥250) for 7+ days Fringe −5 / day drip
Sustained low personal rep (≤−250) for 7+ days Mercantile −2 / day drip
Predatory tariff (≥7%) on owned port for 7+ days Federation, Mercantile, Frontier −15 / week each
Pod-kill anywhere visible to fed-space sector presence Federation −25
Capture a faction-owned planet owning faction −50 (📐 NO-CANON, dormant — see note below)

📐 Capture a faction-owned planet is defined but unwired. emergent_reputation_service.PLANET_CAPTURE_FACTION_PENALTY = -50 and its apply_planet_capture_faction_penalty helper exist and are ready to fire, but the Planet model has no faction-owner field today (planets are owned only by human Players via player_planets, or unowned) — the combat-side caller never resolves an owning faction, so this trigger has never fired in practice. This row is not in ADR-0032's ratified action set; −50 is a NO-CANON proposal mirroring the existing attacked_chartered_planet personal-rep penalty (also −50), picked as "the smallest sensible intervention until canon lands" (per the code's own comment). Activates automatically once planet faction-ownership ships — no additional wiring needed on this side.

Rivalry cascade rule

When Δ_X > 0 to a rivalry-locked faction X, an automatic fractional negative fires to X's canonical rival in the same transaction. Cascades fire on positive deltas only — negative actions do not reward rivals (that path is farmable). Cascades respect F2 decay floor/ceiling and the combined-rep caps.

Source faction Rival Cascade fraction
Terran Federation ↔ Fringe Alliance each direction 0.5×
Mercantile Guild ↔ Shadow Syndicate each direction 0.5×
Frontier Coalition ↔ Astral Mining each direction 0.4× (📐 — promoted to combined-rep cap 700)
Nova Scientific Institute ↔ Astral Mining each direction 0.4× (📐 — promoted to combined-rep cap 700)
Federation → Pirates one-way 0.2× (📐 — one-way Pirate cascade)
Fringe → Pirates one-way +0.1× (clamps at 0; never positive) (📐 — one-way Pirate cascade)

✅ Shipped — the dispatcher computes the cascade on positive deltas and applies the two fully-seeded 0.5× pairs (Terran Federation ↔ Fringe Alliance, Mercantile Guild ↔ Shadow Syndicate); the rows flagged 📐 are registered but not yet live (await the combined-rep cap / Pirate-cascade machinery).

Anti-symmetric matrix (selected multi-faction events)

Some actions move multiple factions simultaneously beyond the rivalry cascade. Fired by the same apply_emergent_action wrapper as a single transactional event.

Action TF MG FC AM NS FA SS PI
Kill Pirate in Fed-Controlled sector +10 0 0 0 0 −5 0 −10
Refine Shard at Nova facility +2 0 0 −2 +8 0 0 0
Refine Shard at Syndicate shadow venue −3 −5 0 0 −2 +1 +6 0
Smuggle through Fed (evade scan) −25 −5 +1 0 0 +10 +5 +1
Smuggle through Fed (caught) −150 −10 0 0 0 +10 +5 +5
Genesis-deploy in Frontier zone −10 0 +75 −10 +5 +5 0 0
Build a public toll warp gate ✅ 0 +30 +5 0 +5 0 0 0
Build a private/whitelist warp gate −5 0 +5 0 0 +5 +10 0
Tow a non-team-mate home +2 +5 +15 0 0 0 0 0
Buy PREMIUM insurance ✅ 0 +10 0 0 0 0 0 0
Donate xeno-artifact to Nova +5 0 +2 −10 +30 0 0 0
Pay pirate tribute −5 −2 −2 0 0 +2 +1 +2 (toward 0)

✅ on a matrix Action cell = live apply_emergent_action call site (BUILD_PUBLIC_WARP_GATE at gate activation; BUY_INSURANCE_PREMIUM at hull insurance purchase). Unmarked rows remain 📐 Design-only.

Ongoing-state drip mechanics

Several rep effects are drips on persistent states rather than one-shot events. Per-tick updates are accumulated and flushed hourly by the wrapper.

State Effect
Wearing a faction-issued ship skin in issuing-faction territory +1/hr issuing faction
Wearing a faction-issued ship skin in rival territory −2/hr rival faction
Carrying contraband openly through a Fed-Controlled sector −1/sector hop Federation
Sustained personal_reputation ≥ +250 (Heroic+) for 7+ days −5/day Fringe
Sustained personal_reputation ≤ −250 (Outlaw+) for 7+ days −2/day Mercantile
Active Wanted Status, docked at a Fringe port +1/hr Fringe (welcomes fugitives)

Refinery-of-record provenance

📐 Design-only. Every Quantum Crystal carries a refined_at_faction_id provenance tag. Using a Crystal in a warp gate Phase 1 commit (per ADR-0029) awards +25 to the refining faction at gate-activation. This single hook makes refining venue choice load-bearing for the late-game arc — the Crystal is anonymous fungible economically but politically remembers where it was minted.

Witness mark

📐 Design-only. When a faction patrol fights in a sector and the player neither engages nor flees, a neutral witness mark accrues against that patrol. Three witness marks at the same patrol convert to +5 of that faction. Rewards "being there" without role-play cosplay; ties peripheral participation to faction identity.

Per-day throttle

To prevent farming, each (player, faction) pair caps at 10 events/day. Once the cap is hit, that faction's positive award is skipped entirely for the rest of the day (a full stop rather than ADR-0032's half-rate continuation). Implemented at the apply_emergent_action dispatcher before write.

✅ Shipped — the per-(player, faction) 10-events/day cap (full-stop variant) is enforced in emergent_reputation_service.apply_emergent_action on positive direct deltas, with counters held in player.settings JSONB under emergent_rep_throttle (no migration).

Global daily pool (per ADR-0056 N-V1). On top of the per-faction cap, each player has a single daily pool that aggregates the sum of positive faction-rep deltas across all factions. Launch value: 100 rep / day. When the pool is exhausted, further faction-rep gains drop to 0 for the rest of the day (the action itself still applies — cargo delivered, NPC killed — but the rep delta is zeroed). Negative deltas are not throttled. The pool resets at UTC midnight.

✅ Shipped — the 100-rep/day global pool clamps each positive award to the pool remaining; negatives never consume the pool or a per-faction event count; the bucket carries its open-date and resets when the stored UTC date is no longer today.

The two redemption-arc actions in the cascade-recovery section below are the only canonical bypasses of the global pool.

Additive amendment (per ADR-0091 §8 Amendment A): the same ADR-0056 detection substrate also gates planet-settlement contests via the settle_contest surface — a HARD-flagged cluster member cannot contest (settle) a planet. See ../../OPERATIONS/multi-account-detection.md.

These numbers are launch balance targets; the underlying API (faction_service.update_reputation(player_id, faction_id, change, reason)) accepts an arbitrary signed integer, so live tuning happens by adjusting the values that game code passes in, not by changing the schema.

Cascade lockout — redemption arc

Per ADR-0056 N-F2. A player who has drifted into deep Pirate alignment (via the rivalry-cascade rule above) needs a discrete break-out path back toward Federation. Two new entries in the action-delta table provide it:

Action Faction-rep delta Notes
Voluntarily destroy a captured pirate Stronghold or Outpost +500 Terran Federation, −500 Pirates Sacrifices the captured holding (no salvage, no compensation). Clears Pirate-alignment cascade lockout. One-shot per captured holding; can be repeated across multiple holdings. Bypasses the global daily pool — this is the recovery vehicle, the cap would defeat the purpose.
Donate the wealth from a captured pirate holding to Federation +200 Terran Federation, −100 Pirates The captured holding's stored credits + commodity inventory transfer to Federation; the holding itself remains the player's. Subject to the daily pool cap.

The player must own (have captured) a pirate holding per ADR-0047 and ADR-0048 to use either action — these are not paths tourists or new accounts can stumble into. ARIA narrates these options when the player's faction-rep enters cascade-lock state, so the path is discoverable without a dedicated UI surface.

Faction-rep ↔ personal-rep — disjoint scopes

Per ADR-0056 N-D1. Faction reputation (this section) and personal reputation (per ./ranking.md) are independent signals. They do not cross-feed unless explicitly enumerated. A single in-game action can carry both a faction-rep delta and a personal-rep delta — they apply in parallel inside the same transaction; neither dampens or amplifies the other.

Cross-feeds that do exist (Launch list):

Source Trigger Cross-feed
Personal → Faction Entering Wanted Status −50 rep with all Federation factions; +25 rep with all Pirate factions; one-shot at the Wanted-Status state-edge, not per-action
Personal → Faction Wanted Status clears No reverse cross-feed; the original deltas are not refunded

Future cross-feeds must land in this table via a new ADR.

Reputation decay

Reputations outside the ±100 band decay back toward that band when the player has not interacted with the faction for over 30 days:

  • Inactivity threshold: 30 days since Reputation.last_updated.
  • Decay rate: −1 point per inactive day past the threshold.
  • Per-call cap: max 50 points of decay applied in a single apply_reputation_decay invocation.
  • Decay floor / ceiling: positive reputations decay toward +100 (never below); negative reputations decay toward −100 (never above). The −99 to +99 neutral band is preserved as-is — values inside it never decay.
  • Pause flag: Reputation.decay_paused (admin lock) and Reputation.is_locked skip decay entirely.

Each decay event appends to Reputation.history JSONB with reason: "Inactivity decay (<N> days idle)" for audit.

Rivalries

FACTION_RIVALRIES defines combined reputation caps:

  • Terran Federation ↔ Fringe Alliance — combined max 800.
  • Mercantile Guild ↔ Shadow Syndicate — combined max 600.

Gaining standing with one faction effectively caps how high you can climb with its rival.

✅ Shipped — the combined-rep cap on positive gains is enforced in apply_emergent_action via a synchronous replica of FactionService._apply_rivalry_cap reading the same FACTION_RIVALRIES table; the two fully-seeded pairs above are live, and a positive delta is clamped so the rival pair never exceeds its combined ceiling.

📐 Design-only — additional rivalries (per ADR-0032) promoted to combined-rep caps:

  • Frontier Coalition ↔ Astral Mining Consortium — combined max 700.
  • Nova Scientific Institute ↔ Astral Mining Consortium — combined max 700.

Territory & influence

Each sector's relationship to a faction is described by an influence percentage (0–100) on the per-(sector, faction) SectorFactionInfluence row. The percentage drives a four-tier territory taxonomy used by patrol and pricing logic:

Territory state Influence Behavior
Core 100% Faction HQ and immediate vicinity. Patrols guaranteed; hostile-reputation players attacked on sight.
Controlled ≥ 75% Faction port presence; frequent patrols; minor penalties for hostile reputation.
Contested 40–60% across two or more factions Mixed patrols; PvP-friendly; port prices follow the dominant-influence faction's reputation rule for the player.
Uncontrolled 0% Pirate spawn zones; no faction benefits or penalties.

Dynamic influence

Player actions adjust influence. Targets — design balance, may be tuned at launch:

Action Effect Tip status (46bce720)
Defend a faction-flagged sector (drone defense survives an attack) +1% influence for that faction ✅ tip-shipped — apply_defense_survived_sector_influence (faction_service) hooked from combat_service drone-defense survival (PR #770)
Destroy a rival-faction ship −2% rival influence ✅ tip-shipped — apply_rival_kill_sector_influence (faction_service) hooked from combat_service ship-destroy resolution (PR #770); unit test_kill_defend_sector_influence
Build a warp gate connecting two sectors +5% influence in the connecting sector for the gate-builder's dominant-rep faction 📐 Design-only — no tip call site
Establish a colony in-sector +3% influence for the player's dominant-rep faction 📐 Design-only — no tip call site
Open a player port at fair tariff (5–6%) for 30 days +2% influence for the dominant-faction of the host sector 📐 Design-only Soft-HOLD — Dynamic +2% influence call site not tip-ancestor (PR #762 Soft-HOLD; do not invent); fair band = tip MIN_TAX_RATE..FAIR_TARIFF_MAX

Influence effects

  • Port prices swing ±10% based on the dominant-faction reputation of the player.
  • Patrol spawn rate scales with influence — higher influence means more friendly patrols.
  • Pirate spawn rate is inversely proportional — high faction influence suppresses pirate encounters.
  • Emergent rep triggers in high-influence sectors weight toward the dominant faction (kills, defenses, discoveries credit the dominant influencer; secondary influencers ≥25% receive half-share rep).

🚧 PartialSectorFactionInfluence schema + write path (faction_service.adjust_sector_influence) are on the feature tip; kill −2% / defend +1% Dynamic influence call sites tip-shipped on 46bce720 / #770; ADR-0021 read-side (territory taxonomy via sector_territory_tier, patrol_spawn_weight derivation + Loop B read, UTC idle daily decay) is implemented on LEG-INI-05 branch / pending merge (6d42bf2c / PR #603open as of 2026-08-20, tip_HAS_land=NO vs 46bce720; Fibril Soft-ORDER #1634 / LEG-1558 land path — not tip-shipped). Canonical schema + formulas: ../../DATA_MODELS/gameplay.md#sectorfactioninfluence (LEG-74).

📐 Design-only residuals: - Real Faction.base_patrol_intensity / zone_mod columns (LEG-INI-05 tip uses identity defaults 1.0 × 1.0) - Remaining unwired Dynamic influence action→delta call sites from the table above: warp-gate +5%, colony +3%, fair-tariff streak +2% (kill −2% / defend +1% are not in this residual — tip-shipped on 46bce720 / #770) - Influence-effects prose beyond derived patrol_spawn_weight / taxonomy (port-price swing, pirate-spawn inverse, emergent-rep weighting in high-influence sectors)

Reputation gating — code cross-index

Canon describes faction reputation as one mechanic; gating consumers are deliberately split across independent services (DECISIONS.md faction-rep-gating-cross-index-not-consolidate, 2026-08-04). Do not consolidate them into one gate helper — keep this table current when a new consumer ships so drift is visible.

Surface Gate Service / entry
Station docking / slip access Faction tier vs station threshold docking_service.check_reputation_gate
Takeover / station purchase Trusted+ (Heroic+) buyer tier port_ownership_service buyer-tier gate
Warp-gate traversal Per-gate faction_rep_min / faction_rep_max warp_gate_service._check_faction_rep_layers
Black-market / contraband Fringe (OUTLAWS) ≥ RECOGNIZED contraband_service._passes_rep_gate
Faction-issued bounty collect Issuing-faction tier ≥ gate level bounty_service collector faction gate
Genesis device acquire/deploy Federation reputation bar genesis_service / api/routes/genesis
Tradedock construction access Guest vs full-access thresholds construction_service Task B-2 gates
Ship-upgrade Exalted catalog Faction-tier ship requirements ship_upgrade_service / api/routes/ship_upgrades

Emergent award path (deltas, throttle, rivalry cascade) stays centralized in emergent_reputation_service.apply_emergent_action — that is the write rail; the table above is the read/gating rail.

Source map

Topic Path
Faction service & rivalries services/gameserver/src/services/faction_service.py
Faction model services/gameserver/src/models/faction.py
Reputation model services/gameserver/src/models/reputation.py
Emergent award rail services/gameserver/src/services/emergent_reputation_service.py
Rep-gating consumers see Reputation gating — code cross-index
API routes services/gameserver/src/api/routes/factions.py

Teams (player)

Creation and membership

  • Creation cost: 10,000 credits (TEAM_CREATION_COST in services/team_service.py).
  • Default size cap: 4 members (max_members parameter — configurable per team; the canonical balance target is 4).
  • One team per player: enforced at creation and invite acceptance.
  • 24-hour leave cooldown between teams (design).

Roles

models/team_member.py:TeamRole defines four roles:

  • LEADER — full control: dissolve team, transfer leadership, assign all roles, override any permission. Exactly one per team (resolved via Player.team_id of the leader).
  • OFFICER — invite, kick, manage treasury (subject to permission flags), manage alliances and faction-aligned operations.
  • MEMBER — standard membership; treasury deposit, default vision sharing, no admin actions.
  • RECRUIT — probationary; deposit-only treasury access, no invite/kick rights.

Granular per-member permissions sit on TeamMember as a mix of explicit booleans (can_invite, can_kick, can_manage_treasury, can_manage_alliances) and a free-form permissions JSONB column for future extensions.

Treasury

Shared resource pool with 12 resource types:

Credits and the canonical 7-commodity catalog (per ../definitions.md#resource-types): Ore, Organics, Gourmet Food, Fuel, Equipment, Exotic Technology, Luxury Goods. Strategic resources also tracked: Quantum Shards, Quantum Crystals, Lumen Crystals, Prismatic Ore.

Operations: deposit, withdraw (permission-gated), transfer between members — credits and quantum_crystals only (PLAYER_TRANSFERABLE_RESOURCES whitelist); the other 10 resource types can be held in the treasury (server-fed, e.g. loot) but are not player-movable — plus transaction history across all 12 types.

Status: ✅ Deposit / withdraw / transfer + balance are shipped and live-proven (2026-06-14, see FINDINGS.md) — wired to the player-client team Treasury tab. ✅ Transaction history is a dedicated ledger: each treasury movement writes a TreasuryTransaction row to the team_treasury_transactions table (services/gameserver/src/models/treasury_transaction.py), capturing team_id, resource_type, kind, amount, balance_after, actor_player_id, reason, and created_at. Corrected 2026-08-04: the headline above previously read "transfer between members" across all 12 types, contradicted by this same caveat two paragraphs later — headline now states the credits/quantum_crystals-only scope directly.

Combat advantages

  • 60/40 statistical edge against non-team opponents (design).
  • Friendly-fire prevention. ✅ Shipped — enforced pre-lock on ship-to-ship (attack_player) and fleet battles (initiate_battle), plus same-team rejection on planet / sector-drone / warp-gate / port attack entrypoints (CombatService._is_same_team, WO-FIX-FRIENDLY-FIRE-LOCK-PARTIAL-COVERAGE + attack_port residual).
  • Shared sector vision.
  • Coordinated drone deployment.
  • Defensive notifications when any teammate is attacked.

Fleet operations

A team can field fleets — multi-ship formations for coordinated battle. See combat.md for fleet mechanics.

Team reputation with factions

Team has a calculated faction-standing using one of three methods: - Average (default). - Lowest member's standing. - Leader's standing.

Switching method has a 7-day cooldown. Faction interactions treat the team as a unified diplomatic entity.

Status: ✅ Compute + expose + notify are shipped and live-wired (WO-RT-TEAM-REP). ✅ Trade pricing consumes team standing on tip 46bce720 / #752FactionService.get_trade_modifier resolves via resolve_effective_faction_standing_value (team TeamReputation aggregate when the player has a team_id; otherwise personal Reputation). ✅ Port-access dock reputation gate (docking_service.check_reputation_gate) resolves via the same helper on tip 46bce720 / #753 (LEG-814). 🚧 Mission-gate consumers of team standing remain not yet built (Soft-HOLD #1305) — do not read pricing+port-access land as universal interaction coverage.

Source: services/team_reputation_service.py; api/routes/teams.py (GET /teams/{team_id}/reputation, PUT /teams/{team_id}/reputation-method); schema on TeamReputation (models/reputation.py).

Methods_aggregate_value per faction, over each team member's Reputation.current_value for that faction (a member with no row contributes NEUTRAL (0), matching Reputation's own default): - Average (default) — round(mean(member_values)). - Lowestmin(member_values). - Leader — the team leader's own value for that faction (NEUTRAL (0) if the leader has no Reputation row). - An empty team (zero members) degrades to NEUTRAL (0) under every method.

Recalculationrecalculate_team walks the full faction catalog every run (not just factions a member has interacted with), so a team's faction_reputation snapshot always has a complete, predictable shape. Each faction's aggregated value is mapped to the same 16-tier ReputationLevel ladder (EXALTEDCRIMINAL/PUBLIC_ENEMY) faction_service uses for individual players. A tier change since the prior snapshot appends to pending_notifications and fires a team_reputation_changed realtime event to the team's websocket room; the very first computation for a faction is never itself treated as a "change." [NO-CANON] the recalculation cadence itself — canon states only that a standing exists and updates, not how often; the service defaults to daily (RECALCULATION_INTERVAL), flagged for DECISIONS.

Method switch (PUT /teams/{team_id}/reputation-method, team leader only) — validates the requested method, enforces the 7-day cooldown against the most recent method_switch entry in TeamReputation.history (a 409 with retry_after if still cooling down), records the switch, and forces an immediate recalculation on success.

Read path (GET /teams/{team_id}/reputation, team members only) — lazily creates a team's TeamReputation row on first read (starts on AVERAGE, due for recalculation immediately) and recalculates inline if the stored snapshot is past next_recalculation, so a fresh team's standings self-heal instead of sitting empty. This read-triggers-refresh path remains a [NO-CANON, pragmatic interim] self-heal for stale snapshots. The scheduler sweep counterpart (sweep_due_team_reputations, gated behind a TEAM_REPUTATION_SWEEP_LOCK_KEY advisory lock) is live-wired: _run_team_reputation_sweep_sync in scheduler/reputation_team_sweeps.py invokes it, and the NPC scheduler core loop calls that helper each tick (scheduler/core_loop.py; re-exported via npc_scheduler_service). [NO-CANON] sweep/recalculation cadence itself is still flagged — not ratified by this wiring-status correction.

[RESOLVED 2026-08-04 — DECISIONS team-reputation-calculation-method-canonical / 093c38ee]TeamReputation.calculation_method is the single source of truth. Team.reputation_calculation_method is deprecated (comment-only; column retained pending a Max-gated DROP). The service never reads or writes the Team-level column.

War system (partial)

🚧 Partial — declarations, PvP-kill scoring, ceasefires, threshold-based victory, and the provisional per-member credit payout are shipped on the gameserver. Player-client war UI is ✅ Implemented on LEG-73 tip / pending merge (2dbd7773 / PR #606open, not yet on feat/new-feature-development). Reputation and other non-credit victory rewards remain unbuilt.

Source: api/routes/teams.py (declare_war/list_wars/ceasefire, /{team_id}/wars/*); services/team_war_service.py (record_pvp_kill, _apply_victory_payout, the resolution loop); player-client TeamWarPanel on LEG-73 tip (PR #606).

Declare (POST /teams/{team_id}/wars/declare, team leader only) — records a mirrored active_wars entry in member_roles JSONB on both teams ({target_team_id, declared_by, declared_at, reason, status: "active", score: {us: 0, them: 0}}). Cannot declare on your own team or on a team you're already at war with. Both team rows are locked in ascending-id order to avoid an AB-BA deadlock against fleet_service's concurrent-battle team locks.

Scoringteam_war_service.record_pvp_kill fires on a resolved PvP ship-kill. If attacker and defender are on different teams that hold a mutual status: "active" war entry, it increments the kill count on both sides' JSONB entries (mirrored: attacker's us == defender's them). Never raises into combat resolution (defensive wrapper at the call site).

Victory — the first side to reach VICTORY_KILL_THRESHOLD = 10 kills auto-flips both war entries to status: "ceased", cease_reason: "victory", with winner_team_id/loser_team_id recorded. The 10-kill threshold is a NO-CANON provisional number (team_war_service.py:37) — this doc previously gave no kill threshold at all, so a concrete gate was needed to let wars end without a manual ceasefire; it awaits DECISIONS.md ratification, same as the other unratified magnitudes this session (loot-mint band, surplus-pioneer rate).

Victory payout — on threshold victory, _apply_victory_payout credits each living member of the winning team VICTORY_PAYOUT_PER_MEMBER = 5000 credits. The 5,000cr-per-member magnitude is a NO-CANON provisional number (team_war_service.py:38) — same ratification class as the 10-kill threshold above; it awaits DECISIONS.md ratification. No reputation or other non-credit victory rewards are paid.

Ceasefire (POST /teams/{team_id}/wars/ceasefire, leader of either involved team) — manually flips a mutual active entry to status: "ceased" without requiring victory.

List (GET /teams/{team_id}/wars, optional ?status=active|ceased filter). ✅ ShippedWarEntry response_model exposes cease/victory fields (ceased_at, ceased_by, cease_reason, winner_team_id, loser_team_id, victory_at) so persistence is not stripped at the API boundary (PR #609 MERGED → 0f35af32, tip-ancestor on 46bce720).

Player-client UI — ✅ Implemented on LEG-73 tip / pending merge: TeamWarPanel (declare / list active|ceased / ceasefire / victory rendering) wired into TeamManager and the Crew dossier — PR #606 @ 2dbd7773 (open, not yet on feat/new-feature-development).

Not built: reputation or other non-credit victory rewards for the winning team.

Alliances (design only)

📐 Design-only — multi-team coalitions with shared vision, no-fire pacts, council voting.

Source map

Topic Path
Team service services/gameserver/src/services/team_service.py
Team reputation service services/gameserver/src/services/team_reputation_service.py
Team war service services/gameserver/src/services/team_war_service.py
Team model services/gameserver/src/models/team.py
Team member roles services/gameserver/src/models/team_member.py
Team API services/gameserver/src/api/routes/teams.py
Team war player UI 🚧 tip-absent — source map historically cited TeamWarPanel.tsx; git grep TeamWar under services/player-client on origin/feat 46bce720 is empty. Do not treat as player-live.
Fleet service services/gameserver/src/services/fleet_service.py
Crew / team console services/player-client/src/components/teams/TeamManager.tsx
Faction standings MFD services/player-client/src/components/mfd/pages/ReputationPage.tsx
Name-color HUD services/player-client/src/components/layouts/StatusBar.tsx (name_color)

Player-facing affordances

Verified vs Sectorwars2102 origin/feat 46bce720. Canon: you do not join an NPC faction.

  • Team create / invite / kick / treasury / chatTeamManager.tsx CREW MANIFEST (teamAPI.createTeam, inviteMember, treasury deposit/withdraw/transfer). TeamSummaryTab.tsx is a compact layout surface.
  • Faction standings (not join)ReputationPage.tsx lists per-faction factionAPI.getReputation() + catalog merge; live-patch on reputation_changed / team_reputation_changed WS. No “join faction” control.
  • Personal name colorStatusBar.tsx paints playerState.name_color (ranking / Wanted chroma, not a faction-join UI).
  • 🚧 Team-war panel — GS team_war_service.py may exist; player-client TeamWarPanel.tsx is not on tip (git grep TeamWar empty). Keep 🚧 until a land SHA is a tip ancestor.
  • 🚧 Faction consumption of team standing — ✅ pricing via get_trade_modifier tip-shipped (46bce720 / #752); ✅ port-access via check_reputation_gate tip-shipped (46bce720 / #753 / LEG-814); 🚧 mission gates from team-rep still unbuilt (this page § Team reputation Status / Soft-HOLD #1305).
  • 📐 Galactic Concord / The Cabal — Design-only on this page’s faction table; do not ✅ a Concord/Cabal join or dossier UI.
  • 📐 Multi-team alliances — § Alliances remains design-only.

Quick comparison

Faction Team
Members NPC organization Up to 4 player accounts
Joining Implicit (you have standing with all of them) Explicit invite/create
Multiple Yes — standing with all simultaneously One team per player
Resource sharing No Treasury (12 types)
Combat coordination No Yes (fleets, formations, vision sharing)
Reputation effect Per-faction pricing + port access + patrol response Aggregate team-wide diplomatic standing
Cost Free 10,000 credits to create
Persistence Permanent Disbandable; 24h re-join cooldown