# Stargate Network Build Record

## Purpose

Use this file as the working decision log for architecture, gameplay constraints, and unresolved implementation questions.

## Project Scope

- OpenSimulator Stargate network with persistent gate registry.
- Atlantis-style gate presentation with animated dialing sequence and chevron lighting.
- Central API for registration, status, routing, and administration.
- Database-backed tracking of gates, regions, grids, and dial history.
- Database-backed address book used by in-world menus for automated dialing.
- Front end website for public browsing and operator management.
- Hypergrid support gated by ZPM power rules for roleplay.
- Hypergrid support gated by power rules for roleplay; multiple ZPMs stack their charge, Naquadah generators provide sustained lower-class power for the electrical grid and local dialing.

## Proposed Capability Breakdown

### In-world Capabilities

- Gate deployment bootstrap
- Self-registration
- Scheduled heartbeat reporting
- Atlantis-style ring and chevron animation sequencing
- DHD or gate menu with remote address book lookup
- Local dialing
- Hypergrid dialing request
- ZPM presence and charge validation
- Power device presence and charge validation (multiple simultaneous ZPMs, Naquadah generators)
- In-world electrical grid bus management and consumer broadcasts
- Public vendor distribution terminal for gate, DHD, and ZPM starter kit delivery
- Failure handling and retry logic

### Backend Capabilities

- Gate identity and authentication
- Address resolution
- Address book delivery for in-world clients
- Address book search by name, public address, region, or grid with online-status weighting
- Random destination selection filtered by type, ZPM requirement, and access level
- Online and offline detection
- Hypergrid route validation
- ZPM authorization rules
- Power authorization rules: ZPM-class threshold for hypergrid, Naquadah-class threshold for local and grid supply
- Multi-device aggregation: combined charge pool across all attached ZPMs; Naquadah generators reported as continuous output rate
- Electrical grid consumer registry per region bus
- Developer add-on broker API with scoped keys, command allow-list, and signed async responses
- Audit logging
- Admin controls

### Front End Capabilities

- Public gate directory
- Region and grid views
- Gate detail pages
- Address book administration
- Searchable gate directory with filters (type, grid, online status, ZPM required)
- Admin dashboard
- Event logs
- Health and alert views

## Open Questions

1. What scripting language and function set will be used in-world: LSL-compatible only, OSSL-assisted, or custom region module support?
2. Will the network operate on one grid first or support multiple grids from day one?
3. How should gate addresses be displayed to players versus stored internally?
4. Should the address book be global, owner-scoped, gate-scoped, or user-scoped?
5. How much animation fidelity is required for the Atlantis-style sequence given simulator performance limits?
6. Should menu-based automated dialing be available to everyone, or restricted by role, group, or owner?
7. Should newly registered gates be auto-approved or require admin approval before they appear publicly?
8. How should ZPMs be represented: inventory asset, linked prim controller, wearable-like object, or pure metadata?
8. How should ZPMs and Naquadah generators be represented in-world: linked prim controllers, separate rezzed objects, or pure server metadata?
9. Multi-ZPM stacking model: do all ZPMs drain equally in parallel, or does the system drain from highest-charged first and cascade?
9a. Naquadah generator power class: can stacked generators ever meet the hypergrid threshold, or is at least one ZPM always required?
9b. Electrical grid consumers: scripted objects subscribing to a bus channel, or purely server-side accounting?
10. How often should gates heartbeat, and after how long should they be considered offline?
11. Do you want a region-side plugin later for richer telemetry than object scripts can provide?
12. Developer addon governance model: open self-service app registration or approval-based onboarding with manual scope grants?

## Risks

- Automatic tracking is only as reliable as the gate deployment package or region module coverage.
- In-world scripts can be copied or tampered with unless registration and token controls are designed properly.
- Hypergrid behavior can vary depending on the OpenSimulator configuration and external destination availability.
- Client-side only ZPM enforcement will not be trustworthy.
- High-fidelity animation can become script-heavy if chevrons, ring lights, sounds, and menus are not partitioned cleanly.
- Real-time address book lookups need caching or fallback behavior when the API is slow.
- Too much logic in scripts can become brittle due to simulator script limits and HTTP throttling.
- Third-party addon API misuse can become a control-plane risk unless command scopes, replay protection, and rate limits are strictly enforced.

## Default Technical Recommendations

- Use PostgreSQL as the system of record.
- Use a typed JSON API with signed gate credentials.
- Treat the backend as authoritative for registration, route approval, and hypergrid eligibility.
- Keep animation and UI scripts separate from registration and heartbeat logic.
- Cache the address book locally for a short period so automated dialing still works during transient API issues.
- Keep the first OpenSimulator scripts thin and state-driven.
- Build the front end only after registration and heartbeat flows are proven.

## Provisional Functional Spec

### Dialing Flow

- Player opens DHD or gate menu.
- Gate loads cached address book entries and refreshes from the API when possible.
- Player selects a destination or enters a manual address.
- Gate performs local prechecks.
- Atlantis-style dialing animation begins.
- Final route authorization occurs near the end of the sequence.
- On approval, the wormhole opens and the session is tracked.
- On rejection, the failure state is played and the gate returns to idle.

### Canonical Internal Models

- Gate identity: server-issued gate_id plus signed gate token.
- Player-facing address: short public address or alias.
- Routing address: ordered symbol array used for animation and authorization.
- Destination class: local or hypergrid.
- Power requirement: none, optional, or required.

### Recommended First Defaults

- Public addresses should be human-readable aliases, not raw UUIDs.
- Route symbols should be stored as ordered arrays, not a single opaque string.
- Address books should combine a global directory with gate-local favorites.
- Hypergrid entries should always require server revalidation even when cached.
- Final route authorization should happen after the visible dialing sequence has nearly completed.

## Suggested First Prototype

- One packaged gate object with config notecard or embedded endpoint settings.
- One registration endpoint.
- One heartbeat endpoint.
- One address book endpoint.
- One in-world vendor object preloaded with gate, DHD, and ZPM assets.
- One gates table.
- One simple web page listing active gates.

## Decision Log

### 2026-04-04

- Initial roadmap drafted.
- Self-registration identified as the most practical automatic discovery mechanism.
- Backend-authoritative ZPM checks identified as required for hypergrid roleplay enforcement.
- Atlantis-style dialing sequence and chevron lighting added as explicit product requirements.
- Database-backed address book added as a first-class feature for menu-driven dialing.
- Initial Atlantis dialing state machine and API contract draft documented.
- Modular script split recommended: gate controller, animation controller, menu controller, address book, heartbeat, and ZPM scripts.
- Address book confirmed as searchable: full-text search by gate name, public address, region, and grid; results weighted by online status.
- Random dial feature confirmed: API returns a random eligible online gate filtered by destination type, ZPM availability, and access level; intended for player exploration.
- Vendor feature confirmed: in-world ESN vendor can deliver gate, DHD, ZPM, or full starter kit bundle.
- Multi-ZPM stacking confirmed: multiple ZPMs can be active simultaneously; their charge combines into a single pool for authorization checks.
- Naquadah generators confirmed as a second power class: sustained constant output rather than depletable charge; sufficient for electrical grid loads and local dialing; not sufficient alone for hypergrid jumps.
- In-world electrical grid confirmed: power management script acts as a bus controller broadcasting available power to subscribed consumer objects (lights, consoles, forcefields, doors); gate dialing takes priority over grid consumers during active wormholes.
- Power device model updated: `power_devices` table replaces `zpm_devices`; type field distinguishes `zpm` from `naquadah_generator`; multiple rows per gate or bus node.
- `power_grid_nodes` and `power_consumers` tables added to track region-side bus state and subscribed devices.
- Developer add-on API confirmed: addons can issue approved commands and receive asynchronous responses through a secure broker API only, with scoped keys, HMAC signing, idempotency keys, and full audit trails.

### 2026-04-05

- OpenSim linked-message compatibility issue confirmed: some `link_message` deliveries expose literal `NULL_KEY` text in `id`, which masked light and sound OFF-style commands when scripts trusted `id` first.
- `stargate_lights_controller_v4_minimal_test.lsl` and `stargate_lights_controller_v2.lsl` were corrected to prefer pipe-payload parsing from `str` before falling back to legacy `id` behavior.
- `stargate_sound_controller_v2.lsl` received the same payload parsing fix and had the current uploaded sound UUID set applied.
- The AV tester was expanded into a full EH/shield harness so lights, sounds, EH, and shield behavior can be validated in-world before porting to production scripts.
- `_shield.lsl` was corrected to only JSON-parse payloads when the message is actually a JSON object. Plain-text commands such as `size|...`, `close`, and `die` now parse reliably in OpenSim.
- `_shield.lsl` runtime behavior was standardized: object name remains `_shield`, `close` collapses visuals and then auto-dies, and explicit `die` remains available for cleanup.
- `_eh.lsl` runtime behavior was standardized: object name remains `_eh`, and close now plays the configured close sound before the object dies.
- Final FX sizing was calibrated in-world: EH diameter `5.15`, shield diameter `5.0`.
- Shield operator semantics were renamed from open/close to up/down at the controller level because visible shield behavior maps more clearly to deployment and removal than door-style wording.
- `stargate_gate_controller_skeleton_v1.lsl` was updated to match the tester-proven behavior: separate `ehDiameter` and `shieldDiameter`, `send_shield_up()`, `send_shield_down()`, startup shield-up flow, and SHIELD relay support for `UP` and `DOWN` with `OPEN` and `CLOSE` aliases preserved.
- Current live-deployment risk: the updated loose scripts are not sufficient by themselves; the `_eh` and `_shield` object assets used by `llRezObject` must also contain the updated internal scripts.

### 2026-04-06

- Backend gate registry rollout completed and verified live behind TLS at `https://api.exoticsg.net`.
- End-to-end API path confirmed: register, heartbeat, directory lookup, address-book fetch, dial authorization.
- `stargate_api_bridge_v1.lsl` tested in-world and confirmed to register a live gate and post heartbeat updates.
- Registration-loop issue in bridge fixed by tracking `llHTTPRequest` request IDs in `g_HTTP_PENDING`.
- Gate ID parse offset fixed in bridge registration response parser (restored full `gate_...` IDs).
- Network default changed to Pegasus for current deployment phase via `g_GATE_TYPE = "pegasus"`.
- `stargate_dhd_controller_v3.lsl` added for bridge-backed address-book sync; compile fix applied for reserved identifier usage.
- Next implementation target: wire `stargate_gdo_idc_controller_v1.lsl` to `/api/gates/dial/authorize` and validate denial/allow flows in-world.

### 2026-04-07

- Same-region/local dial hardening completed across controller, DHD, and EH layers to reduce duplicate outgoing opens and shared-channel cross-trigger behavior.
- Destination gate suppression was added for DHD broadcast dials that explicitly target the receiving gate; destination now waits for incoming relay instead of launching its own outgoing sequence.
- Local/same-region payload normalization was tightened so outgoing EH payloads always use the current region name and known target position when available.
- Iris safety defaults were tightened in `stargate_gate_controller_skeleton_v1.lsl`: API iris commands default OFF, external security command source defaults SELF_ONLY, and CLOSE/HIT no longer rez the iris helper.
- Startup iris mute window and startup diagnostics were added (active controller identity, controller-family collision visibility, script inventory dump, and security mode flags).
- Orphan iris cleanup moved from a one-shot scan to a short repeating startup watch that aggressively sends die commands to owner-matched `_iris` and `_lris` helpers.
- Current known behavior: a brief visible iris flash can still occur in some resets before cleanup catches it. This is accepted as a temporary state for now.

### 2026-04-20

- `stargate_wearable_dhd_hud_v1.lsl` was hardened to support live API address-book payload shapes used by the ESN backend.
- HUD JSON parsing now accepts both legacy and bridge-wrapped structures and reads labels from `alias`, `target_short`, `name`, `gate_alias`, and `gate_name` fields.
- HUD route parsing now supports symbol arrays (`symbols`, `symbol_list`) and converts them to CSV dial routes.
- Gate discovery and select labels were standardized to use operator-defined short names for the current environment: `CAST` and `CELESTIS`.
- Address-book dialing reliability was improved using a direct gate send plus channel fallback strategy.
- HUD reset behavior was updated to close the last dialed source gate, with fallback delivery for multi-prim controller layouts.
- Operational validation completed in-world: address book entries populate, CAST selection dials successfully, and reset command is sent to the last dialed gate context.
