REMI 2.1 — Windows website hosting
==================================
Windows build 11 (2.1.0.10), 64-bit Windows 10/11
Includes the updated experimental Synonym Finder.
Security update: Werkzeug 3.1.9 rejects unsafe Windows static-file paths.

Install and launch
------------------
For an existing Windows Build 6 through 10 installation, use the Build 11
Website Update ZIP and its Apply-Update.txt. It includes the earlier
sign-in and security fixes and uses the existing Caddy and host settings.

1. Close personal REMI and Host REMI Website before updating.
2. Run REMI-2.1-Windows-x64-Web-Hosting-Setup.exe from the extracted ZIP.
3. Open Host REMI Website from your desktop or Start menu.
4. Start with "This computer (preview)" and select Start website.
5. The browser opens the API-key entry page. Each visitor must enter and
   verify their own NCBI API key before using search tools.

Python and application dependencies are bundled. No separate Python, Redis
or database installation is needed. The host does not need a shared NCBI key.
The existing REMI shortcut still starts personal REMI with its saved key;
its control window also has a Host REMI Website button.

Keep the hosting control window open. Stop & close, closing the window,
restarting the host, or shutting down Windows ends all website sessions.
Personal REMI and the website run in separate processes and can run together.

Choose how visitors connect
---------------------------
This computer (preview):
  Only this computer can connect, normally at http://127.0.0.1:8080/.
  Remote HTTP requests cannot enter an API key in this mode.

Trusted local network (HTTP):
  The server listens on all IPv4 interfaces at the selected port. The control
  window shows detected network addresses that other computers can open.
  Windows Firewall and your network must permit connections to this port.
  This mode sends API keys over unencrypted HTTP: use only on a trusted local
  network. The entry page clearly identifies that transport. Do not expose
  this HTTP port to the public Internet.

Public website (HTTPS proxy):
  Set an address such as https://remi.example.org and the internal server port
  (default 8080). REMI listens only on 127.0.0.1. A reverse proxy on the SAME
  computer must provide HTTPS at your configured address. Public mode rejects
  insecure requests and unexpected Host headers and uses Secure cookies.

  This installer starts the REMI application server. It does not register a
  domain, obtain certificates, install a reverse proxy, change firewall/router
  rules, or publish a public URL. Those depend on your hosting environment.
  Your server must remain powered on and connected while visitors use REMI.

Example public setup with Caddy
-------------------------------
Have the server/network administrator point remi.example.org to this computer
and make Caddy reachable on ports 80/443. Obtain Caddy from its official site:
    https://caddyserver.com/docs/install

Copy hosting/Caddyfile.example to a writable folder, rename it Caddyfile,
replace the example domain, and match the internal port selected in REMI.
From that folder, run:
    caddy run --config Caddyfile --adapter caddyfile

Start REMI in Public website mode using the same HTTPS domain, then visit
that HTTPS address. Caddy handles HTTPS and forwards to localhost; REMI only
trusts the X-Forwarded-Proto header from the local proxy. Preserve the Host
header. Do not run multiple REMI website server processes behind a proxy.
For unattended hosting, configure the processes through your normal server
management. The installer does not add Windows services or startup entries.

Official deployment references:
    https://flask.palletsprojects.com/en/stable/deploying/waitress/
    https://docs.pylonsproject.org/projects/waitress/en/latest/reverse-proxy.html
    https://caddyserver.com/docs/quick-starts/reverse-proxy

Sessions, keys and concurrent searches
--------------------------------------
Each browser session has private variants, results, progress and cancellation.
Different people should use different browser profiles/devices. Tabs in the
same browser profile share a session. No REMI account is required.

Visitor keys are held only in the website process's memory, never in config
files, browser storage, cookies or PubMed request URLs. The host processes
keys and must be trusted. Cookies contain only random session IDs and CSRF
tokens. Standard application logs omit keys and search-query debug output.
Do not configure your reverse proxy to log request bodies containing keys.

End session clears that session's stored key/results and cancels its work.
Sessions also expire after 30 minutes of inactivity. A request already in
flight may take up to its network timeout to finish; it cannot start another
request after cancellation. Active search polling keeps the session active.
Host restarts end all sessions; jobs and visitor results are not persisted.

Search history in the session toolbar lists every submitted Keyword,
Proximity or Synonym Finder search accepted in that session, including repeated
queries as separate entries. Open an entry to restore submitted options,
results, selections and query output without PubMed calls.
History is private to the session, held only in host memory, and cleared on
session end, inactivity expiry or restart. A shared 64 MiB history budget
limits host memory; if exhausted, the site reports it and keeps old entries.
Synonym Finder entries are available while Experimental Features is on.

The single server process runs up to 4 variant-search jobs concurrently and
queues at most 4 more. It permits up to 4 concurrent cleaning streams and
100 visitor sessions. A visitor runs one search or cleaning operation at a
time. Busy responses invite a retry; other visitors' results remain private.
Operations are limited to 30 minutes; website proximity generation is limited
to 50,000 combinations per query. Use fewer terms for larger searches.

All website PubMed calls use up to 10 request starts/second per API key,
including login verification, variant searches, EFetch and cleaning. Visitors
using the same key share its allowance. Usage of that key in other programs
also counts toward NCBI's limit. HTTP 429 delays affect only that key.
    https://ncbiinsights.ncbi.nlm.nih.gov/2017/11/02/new-api-keys-for-the-e-utilities/

Search features
---------------
Keyword Search, normal/Precise Proximity, dates, hyphen options, three-letter
wildcards (app*, app*l), individual iterative exclusions, variant selection,
clipboard and exports remain included. Clean checks clauses sequentially,
removes counts <= the chosen 0–999 threshold, displays progress, retains
failed checks, and preserves the original query on cancellation.

* A number after a wildcard limits the letters at that position in reported
  variants. For tumo*1r*2, tumor and tumours fit; tumorigenic does not. PubMed
  discovery uses tumo*r* and the same iterative exclusions as before.
  If a literal occurs more than once, the reporting limit uses its first
  position that fits the ordinary pattern. For tumo*r*2, tumorspheres is
  excluded because seven letters follow the first r.
* Keyword Search exports selected variants and frequencies as CSV or Word
  (.doc).
* English only adds AND English[la] after the grouped variant discovery query
  on each iteration. It does not filter generated proximity queries or Clean.
* Select Title Search before running a Proximity search, with or without
  Precise Proximity. It searches and mines titles only. Generated queries use
  [ti:~n] for that search; the default remains [tiab:~n].
* Experimental Features in the session banner starts off. Enable it to show
  Smart Identifier in both Proximity modes. Smart Identifier starts unchecked
  with a distance of 3 words.
  Set 0 to 99 intervening words, with 0 requiring adjacent matches. Variant
  counts include only occurrences near a match of the other concept in
  the same title or abstract, in either order. Title Search uses titles
  only. Each qualifying occurrence is counted once even if it has multiple
  neighbors or appears in more than one Precise comparison. Exact terms
  entered as inputs are still available to select. Turn Smart Identifier
  off to use the unrestricted variant list. PubMed discovery and the
  distance for the generated query are separate from this setting.
* Checking Smart Identifier reveals Selective Identifier. Turn it on before
  searching to save the exact nearby pairs in the current search. Generate
  uses only selected pairs observed within the Smart Identifier window and
  the chosen generated distance. Turning Selective Identifier off restores
  all selected combinations for generation.
* Show omitted variants reveals actual discoveries hidden by a number limit
  or Smart Identifier. These are unchecked and skipped by bulk selection.
  Check one manually to use it in exports or proximity generation. With
  Selective Identifier on, it still needs an observed nearby partner.
* Developer Mode in the session banner shows the current visitor's queries
  and result counts below the search, including discovery and Clean. The
  latest entries are kept in memory while the mode is on. Query text never
  contains the session's API key; a very long entry may be clipped to fit
  the log. Switching the mode off clears it.
* Synonym Finder appears in navigation when Experimental Features is on.
  Enter one MeSH heading, optionally ending in [mesh]. Each round searches
  PubMed as [majr] and reads up to the first 999 returned titles. Words joined
  with AND can occur anywhere in a title. Within each title, a more frequent
  pair takes priority over a pair with a shared word. Independent pairs still
  count. Pairs and standalone words need at least 10 distinct credited titles
  in a round. The results include the count from the first qualifying round
  and example titles. Asterisks group observed spellings such as breast and
  breasts. Open a cluster to select partners and copy the selected title query.
  The next round excludes discovered wording, using exact observed spellings
  and AND between linked words. The search stops when a round adds no new
  wording or there are no titles left. A query size limit can stop unusually
  large runs and keep their results. The NLM 2026 MeSH reference is used to
  resolve the starting heading; discovery uses the returned titles.
* Clean counts each clause with its original field and distance. Removed terms
  displays the removed clauses and their PubMed record counts.

Settings, troubleshooting and source
------------------------------------
Host settings and status are stored separately from personal REMI at:
    %LOCALAPPDATA%\REMI\website\settings.json
    %LOCALAPPDATA%\REMI\website\website.log
These files contain no visitor API keys. Use another port if startup reports
that the selected port is occupied. The health endpoint is restricted to a
local caller with the host's random control token.

For a console host using the saved settings, from the installation folder:
    python\python.exe -I -X utf8 website_server.py --standalone
Run one instance. Stop it with Ctrl+C. It does not use the personal API key.

The application source and all installer support code are included. New
hosting code is under GNU AGPL v3; see app/LICENSE and app/LICENSE-CONTENT.md.
The entry page and session toolbar offer a downloadable source ZIP at /source.
It contains the modified source and build instructions, never visitor data.
See README-Source.txt for running from source and rebuilding the installer.
Build provenance and personal desktop setup are described in README-Windows.
This is independent packaging, not an official university release.

Verification limits
--------------------
Offline regression and session-isolation tests use controlled PubMed responses.
No real NCBI credentials were used for those tests. The compiled installer is
extracted and byte-compared with the tested payload. The managed browser
preview service was unavailable; real-browser and native Windows installation
checks were not performed here. The installer remains unsigned.
