KELDRIN REMOTE PORTAL
=====================

File to upload
--------------
Keldrin_Remote_Portal_V1.0.34.zip is the clean first-install deployment for
the Keldrin Remote Portal. Upload and extract it into a dedicated directory on
an external HTTPS web server. Do not extract it over an unrelated website.

Why install it?
---------------
- View Keldrin and dedicated-server status from a phone or another computer.
- Use the authenticated remote controls exposed by your selected Portal role.
- Supply the outside-network half of each game tile's External Port Test.
- Review Keldrin activity, performance, backups, and server settings. Saved
  game passwords are available only to an authenticated Portal administrator.

Basic setup
-----------
1. Upload and extract Keldrin_Remote_Portal_V1.0.34.zip on a PHP-capable HTTPS
   web host.
2. Open that HTTPS Portal address in a browser and complete its setup page.
3. Create the matching Site ID and bridge API key in the Portal.
4. In Keldrin Desktop, open Remote Portal Setup, enter the HTTPS Portal URL,
   Site ID, and API key, then choose Save & Test.
5. Keep the API key private. Keldrin stores it locally with Windows DPAPI and
   never displays the stored value again.

External Port Testing
---------------------
The Portal must be hosted outside the network that contains the game server.
Once the Portal is connected and a game is installed, Keldrin continually
refreshes the relevant game tile's outside-network evidence without requiring
a button press. Exact temporary nonce listeners are used only while that game
is stopped; Keldrin does not steal a running game's sockets. Each tile labels
the result and explains that game's exact reviewed protocol and ports. A
successful result is useful router-path evidence; the final proof is still
joining the game from an external computer.

Portal 1.0.34 does not require a private target-policy file for the ordinary
direct-IPv4 case. When data/keldrin-external-targets.php is absent, the Portal
may test only the exact public IPv4 it observed on Keldrin's authenticated
bridge request. A private policy, when configured, remains authoritative.
IPv6/proxy ambiguity, non-public addresses, or a mismatch still fail closed.

Schedule Override
-----------------
An authenticated Portal administrator can enable a temporary schedule
override for 1, 2, 4, 24, or 48 hours, or explicitly choose Never. The
selector defaults to 1 hour. The Portal shows the exact expiry and remaining
time reported by Keldrin. Viewers can see override status but cannot change it.
An unavailable status means the timing evidence was missing, stale, malformed,
or unsupported; it is not reported as Never.

Updates
-------
The clean root ZIP is for a fresh/manual Portal installation and is
deliberately easy to find. It contains the current Keldrin-branded setup page.
Never extract that clean ZIP over an existing Portal. After setup, compatible
Portal updates can be sent from Keldrin Desktop using the signed Portal update
package bundled inside Keldrin. Portal Update in the browser remains the manual
backup path for that same signed update ZIP.

The two update paths are intentionally separate:
- Fresh install only (never update in place): use the clean
  Keldrin_Remote_Portal_V1.0.34.zip beside Start-Keldrin.cmd.
- Browser Portal Update fallback: use the signed
  Keldrin_Remote_Portal_Update_V1.0.34.zip found beside Start-Keldrin.cmd and
  upload it on the Portal Update page.
- Native Keldrin Portal update: Keldrin uses the byte-identical signed copy at
  App\Service\PortalUpdates\Keldrin_Remote_Portal_Update_V1.0.34.zip.

Both Portal 1.0.34 packages declare the same 35-file deployment and target
version, but their index.php and setup.php bytes intentionally differ. The
clean ZIP carries Home-first navigation with no Top links plus the new
Keldrin-branded setup.php for fresh installations. For compatibility with the
existing protocol-v1 updater, the signed update carries all 19
Install=false files byte-for-byte from the cryptographically verified signed
Portal 1.0.21 predecessor, and all 16 Install=true files byte-for-byte from the
clean Portal 1.0.34 deployment. The updater verifies every declared file,
then copies only the 16 Install=true files. It never copies or executes
index.php or setup.php during an in-place update; the updateable app.js applies
the same Home-first navigation at runtime. Existing accounts, configuration,
private keys, audit records, runtime state, and other private data remain
untouched. This boundary is deliberate; it does not relax package verification
or change any Install flag.

The signed update accepts signed-lineage Portal versions 1.0.9 through 1.0.32.
It does not accept 1.0.8, 1.0.34, or a newer version as an update source. A
Portal first installed from a clean ZIP can have different immutable index.php
and setup.php bytes; if it reports stable_boundary_mismatch, perform a
deliberate clean 1.0.34 manual bootstrap while preserving only reviewed private
data.

Reviewed package identities
-----------------------------
- Clean fresh-install ZIP: 94,421 bytes; SHA-256
  E405422FCF4F003EF585D4FD31E3A36D733EE431BF35856E7C5F97DD7E09FA2C
- Signed in-place update ZIP: 96,445 bytes; SHA-256
  055CF85C5C327C4AB26A40E40A4828F857DC457A51E23F343A9CD60308623FF4

Private runtime data, accounts, passwords, API keys, audit history, and server
configuration are not included in this deployment ZIP.
