OpenTrail updates, upgrades, hotfixes and patches
The permanent release ledger for what changed, why it changed, how it was verified, what migrated, and what risk remains.
Current recorded state
This ledger is initialized from the recovered OpenTrail repository snapshot captured on August 5, 2026. Its evidence includes Git history and tags, workspace manifests, CHANGELOG.md, CODE_CHANGELOG.md, HOTFIXES.md, migrations, release notes, and production-verification records.
The manifest, changelog, release notes, health verification, and production evidence all identify 1.1.0 as released. The recovered Git snapshot does not contain a
v1.1.0 tag. That missing tag is tracked as a release-integrity gap; the ledger does not invent it.This page tracks historical and future changes. The main OpenTrail article explains the current application, while the research page records proposals that have not necessarily shipped.
How changes are classified
Stable releases follow semantic versioning: major for incompatible public contracts, minor for backward-compatible features, and patch for backward-compatible fixes, security updates, hardening, and documentation corrections. All workspaces share one version.
Release timeline
| Version | Date | Classification | Evidence state | Summary |
|---|---|---|---|---|
| 0.1.0 | July 21, 2026 | Initial development baseline | Tagged | Monorepo, PostGIS/NestJS/Next.js MVP, Docker and least-privilege database roles, authentication, Oregon data, map exploration, weather, wildfire, reviews, photos, moderation, parking, connections, lodging, sharing, and deployment. |
| 0.2.0 | July 22, 2026 | Moderation upgrade plus operational fixes | Tagged | Photo approval gate, admin photo queue, charter/version policy, 101-check smoke coverage, Docker restart-policy fix, wildfire feed repair, and the photo-moderation migration. |
| 0.3.0 | July 23, 2026 | Administration and performance upgrade | Tagged | User roster and presence, bans, account deletion, session revocation, contribution takedown, viewport caching, single-flight queries, cache observability, and ban/cache regression checks. |
| 1.0.0 | July 30, 2026 | Internal stable-line terrain baseline | Not publicly tagged | Terrain and elevation work was deployed for verification, then superseded by the 1.0.1 public patch. The entry is retained so the skipped tag remains explicit. |
| 1.0.1 | July 30, 2026 | Public terrain and release-hardening patch | Tagged | Elevation profiles, 3D terrain/hillshade, versioned terrain data, resumable backfill, version consistency checks, deployment checklist, dependency hotfixes, runtime-image pruning, and 128 smoke checks. |
| 1.1.0 | August 1–4, 2026 | Bike Access and Suitability upgrade | Documented and deployed; tag absent from recovered snapshot | Legal bike/e-bike access, deterministic suitability, source provenance, corrections and moderation, migration/backfill, filters and map states, 16-source Oregon audit, 20,294 production profiles, and 133 smoke checks. |
The recovered tags are v0.1.0, v0.2.0, v0.3.0, and v1.0.1. Version 1.0.0 was explicitly internal. Version 1.1.0 is supported by deployment and documentation evidence but needs its repository tag reconciled.
0.1.0 — initial development series
The initial series established the platform from July 18 through July 21, 2026 and was recorded as one baseline release.
Application and data
- npm workspace with separate NestJS API, Next.js/MapLibre web client, shared types, and infrastructure.
- PostgreSQL/PostGIS trail schema and Oregon OpenStreetMap import, expanded from roughly 3,600 to 19,900 trails.
- Map-driven radius, viewport, state, and trail-name discovery with prominence ordering.
- Real elevation, reviews, photos, trail-buddy difficulty characters, parking, connections, lodging, and park overlays.
Security and operations
- Argon2id signup/login with revocable server-side and guest sessions.
- Containerized services and separated database roles.
- Review moderation and generated administration account.
- NWS weather, NIFC wildfire integration, deployment script, smoke suite, and an externally exposed web-only boundary.
Baseline fixes
- Corrected an invisible map caused by a CSS cascade conflict.
- Purged junk trail names from imported OSM data.
- Made basemap loading deterministic before expanding visible features.
0.2.0 — moderation and operational fixes
This release closed the path that allowed unreviewed photos to reach public surfaces.
- Uploads begin as
PENDING; only approved photos are public or eligible as covers. - Moderators received approve/reject endpoints, an image-preview queue, and separate pending counts.
- Uploaders can see their own pending media without exposing it to others.
- Unapproved photo identifiers return 404 to unauthorized callers, and pending previews use private/no-store caching.
- Approved-photo cache duration was reduced so later moderation decisions are not hidden by year-long caches.
- The smoke suite reached 101 assertions covering queue authorization, bytes, listing, cover selection, approval, and revocation.
Patches included
- Docker restart patch: database, Redis, MinIO, API, and web gained
unless-stopped; the one-shot migration job remains non-restarting. - Wildfire feed patch: the integration replaced the removed
DailyAcresfield withIncidentSize, stopping silent zero-result degradation.
0.3.0 — administration and viewport performance
The administration upgrade made account enforcement complete, while viewport caching reduced repeated spatial queries.
User administration
- Searchable roster with roles, content counts, join dates, active/banned filters, and throttled presence.
- Admin-only account deletion with safeguards against deleting self or another administrator.
- Bans require a reason, revoke all sessions, reject public photos/reviews, and stop the next authenticated request.
- Unbanning restores access without silently republishing rejected content.
- Login reveals ban status only after a correct password, avoiding account discovery.
Explore performance
- Zoom-aware viewport grid keys reuse nearby results.
- Responses are trimmed back to the requested box so cache snapping never widens returned data.
- Single-flight handling prevents concurrent cold requests from stampeding PostGIS.
- Popularity-aware retention keeps active regions warm.
- Staff cache metrics expose hit rate and hot viewports.
1.0.0 baseline and 1.0.1 public patch
Internal 1.0.0 introduced terrain/elevation capability. It was verified but not separately tagged; 1.0.1 superseded it as the first intended public stable-line release.
Terrain and elevation upgrade
- Versioned trail terrain profiles store compact distance/elevation points, gain/loss, bounds, grade metrics, source, spacing, algorithm version, and computation time.
- A resumable backfill samples public terrain tiles, smooths points, applies gain/loss hysteresis, caps UI profiles, and transactionally updates the legacy gain value.
- Trail details receive an optional additive terrain contract; list responses remain unchanged.
- The web UI adds an accessible elevation profile and a pressed-state toggle between flat and MapLibre 3D terrain/hillshade.
- At rollout, 19,913 of 19,913 trails with geometry had valid algorithm-v1 profiles with none deferred.
Patch and release hardening
- Aligned every manifest, lockfile entry, health response, Swagger surface, and changelog on 1.0.1.
- Added
npm run version:checkas a release gate. - Patched production dependencies and removed development packages from the long-running API image.
- Added integrity checks for profile tuples, elevation bounds, gain/loss, and percentile order.
- Recorded backup, migration, backfill, postflight, and rollback steps in a deployment checklist.
- Production builds, health, real-browser terrain behavior, and 128 end-to-end smoke checks passed.
1.1.0 — Bike Access and Suitability
The upgrade separates legal permission from physical suitability. A route can look rideable without being legally open, so explicit restrictions always override inference and unknown access remains unknown.
Rider experience
- Bike and e-bike access states: allowed, conditional, prohibited, or unknown.
- Estimated MTB suitability with score, confidence, evidence, and human-readable reasons.
- Explore filters, access-colored lines, map legend, cards, detailed profile, and source freshness.
- Evidence-backed correction submissions routed through existing moderation.
Data and rules
- Versioned bike profiles and correction records with provenance and indexes.
- Segment-aware OSM processing for access, conditions, direction, surface, smoothness, visibility, and MTB scale.
- Sixteen reviewed Oregon authority sources.
- Fourteen deterministic fixtures; machine learning intentionally disabled until reviewed labels justify it.
Production evidence
- 20,294 trails and 20,294 rules-v1 bike profiles; complete terrain profiles for mapped trails.
- 1,236 allowed, 322 conditional, 1,382 prohibited, and 17,354 explicitly unknown.
- No missing, invalid, or orphaned bike/terrain rows.
- 133 production smoke checks passed; users, media, moderation, administration, and existing trail behavior remained intact.
- API, web, PostGIS, Redis, and MinIO were healthy, and the public health path reported 1.1.0 through forced HTTPS.
Official-source coverage is incomplete; access can become stale; signs and land-manager notices always win; moderator/import writes still need explicit viewport-cache invalidation; and Redis is healthy while viewport caching remains process-local for the current single API instance.
Hotfix register
| ID | Release | Hotfix | Impact and verification |
|---|---|---|---|
| HF-1 | 1.0.1 | Patched production dependency chain | Next.js, Sharp/libvips, PostCSS, and js-yaml floors or overrides were raised after high-severity advisories. Production audit, builds, image processing, and smoke checks passed. |
| HF-2 | 1.0.1 | Removed development dependencies from the API runner | The long-running API image now receives pruned production dependencies; the one-shot migration image retains the build and Prisma tooling it requires. |
| HF-3 | 1.0.1 | Eliminated release-version drift | Root, API, web, shared package, lockfile, health, Swagger, and changelog were aligned. The version check now fails when these surfaces disagree. |
| HF-4 | 1.0.1 | Made terrain integrity release-blocking | API and smoke checks reject malformed tuples, invalid bounds, negative gain/loss, or inconsistent grade percentiles. All 19,913 geometric trails passed at release. |
Required hotfix procedure
- Assign the next HF identifier and document impact, exposure, and urgency.
- Add or update an automated regression check.
- Run version consistency, production dependency audit, builds, and smoke checks.
- Create and validate a database/object-storage backup when schema or data may change.
- Commit and tag the patch release, then deploy the exact tag.
- Record postflight evidence, accepted risk, rollback state, changelog, code changelog, hotfix register, and wiki entry.
Migration ledger
| Migration | Release | Purpose | Deployment and recovery evidence |
|---|---|---|---|
20260722161500_photo_moderation | 0.2.0 | Added photo moderation state and audit fields. Existing ungated photos intentionally entered the review queue rather than becoming approved automatically. | Deploy migration, inspect backlog, verify public 404/private no-store behavior, then approve content deliberately. |
20260730203000_terrain_profiles | 1.0.1 | Added the one-to-one versioned terrain profile and indexes; refreshed legacy elevation gain from the same algorithm. | Validate backup, migrate, run resumable terrain backfill, verify counts/integrity, then test detail and 3D/flat map behavior. |
20260802070000_phase_2_bike_access | 1.1.0 | Added bike profile and correction records, indexes, provenance, rules versions, and an explicit unknown profile for every trail. | Validate backup, migrate, run source/rules validation and bike backfill, preserve approved official evidence, then verify profile counts and moderation. |
A database migration does not automatically require a major release if the supported API remains compatible and the forward path is documented. Destructive or contract-breaking data changes require a major version and a separately approved recovery plan.
Release verification standard
A manifest bump alone is not a release. A release exists when the version, tagged source, built artifact, migration state, runtime health, public behavior, and documentation agree. Where they disagree—as with the missing recovered 1.1.0 tag—the discrepancy remains visible until reconciled.
Accepted risks and open hardening work
| ID / release | Risk | Current containment | Planned resolution |
|---|---|---|---|
| AR-1 · 1.0.1 | API-wide CSP disabled for Swagger inline assets. | Other Helmet headers remain active. | Isolate/restrict documentation or self-host compatible assets, then enable strict CSP. |
| AR-2 · 1.0.1 | Development-only Nest CLI dependency chain retained advisories. | Pruned from the long-running API; confined to controlled build/migration stages. | Upgrade when a compatible patched upstream chain exists. |
| AR-3 · 1.0.1 | 3D terrain depends on external tile availability. | Stored profile/chart data remains available. | Signed/versioned offline packages with licensing and quota controls. |
| RI-1 · 1.1.0 | Recovered repository lacks the documented 1.1.0 tag. | Manifest, release notes, commit history, health, and production results provide corroborating evidence. | Verify authoritative remote/tag state and create no retroactive tag without release-owner approval. |
| RI-2 · 1.1.0 | Bike access can be incomplete or stale. | Unknown remains explicit; official evidence and current signs override inference. | Expand audited sources, freshness monitoring, corrections, and cache invalidation. |
Template for every future update
Permanent workflow rule
Every OpenTrail change going forward must update this ledger during preflight with the intended scope and during postflight with verified facts. Feature ideas stay on the research or roadmap pages; only implemented and validated work enters the release history.