LibreSign / LibreSign/libresign

Finalize signer geolocation frontend with IP-based location

Open
#8,087 4 comments 0 reactions 1 assignee View on GitHub

@lfals is already working on this.

Since Sep 11, 2026.

feature-request frontend javascript
Dominant language
PHP
Stars
818
Forks
146
Avg merge
11h 31m
Merged PRs (30d)
326

Description

Context

The signer geolocation frontend was introduced in #8085 before the complete geolocation model was defined.

#8086 finalizes the backend contract with two independent location sources:

  • device-reported geolocation;
  • IP-based approximate geolocation.

This issue updates the existing frontend to that final contract and adds the complete frontend support for IP-based geolocation.

It includes:

  • updating the current device geolocation frontend to the final API and policy names from #8086;
  • grouping device and IP geolocation in the Policy Workbench without creating a third policy;
  • configuring the local GeoIP database;
  • displaying GeoIP configuration and validation status;
  • using the final device geolocation contract in request and signing flows;
  • displaying stored device and IP geolocation evidence in the signed PDF Document Validation view;
  • respecting the frozen behavior of existing signature requests.

Blocked by:

  • #8086 — final signer geolocation backend and GeoIP support.

Goal

Provide one clear frontend area for signer geolocation with two independent sources:

Signer geolocation
├── Device-reported location
└── IP-based approximate location

The frontend must make the source of each location clear.

Do not:

  • merge the two sources;
  • calculate one effective location;
  • choose one source as authoritative;
  • automatically compare them.

Device-reported location must not be presented as proof of physical presence.

IP-based location must be presented as approximate and may be affected by VPNs, proxies, mobile networks and similar infrastructure.

Final frontend contract

Update the frontend introduced by #8085 to use the final backend contract from #8086.

Device policy

Replace:

signer_geolocation

with:

signer_device_geolocation

Supported values:

  • disabled
  • optional
  • required
IP policy

Add:

signer_ip_geolocation

Supported values:

  • disabled
  • enabled
Requester field

Replace:

geolocationRequired

with:

deviceGeolocationRequired

This field applies only to device-reported geolocation.

Frozen signer requirement

Replace:

geolocationRequirement

with:

deviceGeolocationRequirement

Signing payload

Replace the client-provided signing field:

geolocation

with:

deviceGeolocation

The frontend must submit only device-reported location.

The frontend must never submit:

  • IP geolocation;
  • GeoIP coordinates;
  • source IP;
  • GeoIP status.

IP geolocation is resolved and stored only by the backend.

Signer geolocation metadata

Read signer geolocation from the backend contract:

{
  "deviceGeolocationRequirement": "required",
  "geolocation": {
    "device": {},
    "ip": {}
  }
}

Only sources returned by the backend are available to the frontend.

Policy Workbench

Present the two backend policies under one Signer geolocation area.

The frontend grouping is only visual.

Do not create or simulate a third master geolocation policy.

Device-reported location

Expose signer_device_geolocation with:

  • Disabled
  • Optional
  • Required

Expected behavior:

  • disabled: device geolocation cannot be required;
  • optional: the requester may require device geolocation for individual signers;
  • required: device geolocation is required for all signers.
IP-based approximate location

Expose signer_ip_geolocation with:

  • Disabled
  • Enabled

Explain briefly that this option uses the signer IP address and the locally configured GeoIP database to obtain an approximate location.

There is no per-signer requester override for IP geolocation.

Existing Policy Workbench behavior

Reuse the existing policy infrastructure and UI behavior for:

  • system scope;
  • group scope;
  • user scope;
  • inheritance;
  • delegation;
  • inherited values;
  • non-editable values.

Device and IP policies must remain independent and use the resolved state provided by the backend.

The GeoIP database path is technical instance configuration and must not appear as a group or user policy.

Policy snapshot behavior

The frontend must respect the frozen behavior defined by #8086.

For a new signature request, use the effective policy state provided by the backend.

After the request is created, its behavior must come from backend data derived from the stored policy snapshot.

The frontend must not resolve policies or reconstruct snapshot behavior itself.

Expected behavior:

  • a request created while a source is disabled stays disabled for that source even if the effective policy is enabled later;
  • a request created while a source is enabled keeps that behavior even if the effective policy is disabled later;
  • new requests created after a policy change use the new effective policy;
  • an existing request without a source in its policy snapshot remains disabled for that source.

For existing requests, backend request data is authoritative.

Request signature flow

Keep the existing device geolocation requester flow from #8085, updated to the final contract.

When signer_device_geolocation is optional, allow the requester to set:

deviceGeolocationRequired

for each signer.

Device policy disabled

Do not show the per-signer device geolocation control.

Device policy optional

Show the per-signer control.

The requester may choose whether device geolocation is required for each signer.

Device policy required

Do not allow the requester to disable device geolocation for individual signers.

The UI may explain that the requirement comes from policy.

Existing requests

When viewing or editing an existing request:

  • use the requirement returned by the backend;
  • do not derive it again from the current policy;
  • do not remove or overwrite the frozen deviceGeolocationRequirement during unrelated edits.
IP geolocation

Do not add any per-signer requester control for IP geolocation.

IP geolocation behavior for an existing request comes from the backend state derived from the frozen policy snapshot.

Signing flow

Device-reported location is the only geolocation source that requires browser interaction.

Use deviceGeolocationRequirement returned by the backend to decide whether device location must be collected for the current signer.

When device geolocation is required:

  • keep the existing information/privacy step before requesting browser permission;
  • request location using the browser Geolocation API;
  • submit it as deviceGeolocation;
  • keep the existing handling for permission denial, timeout and unavailable location;
  • do not reuse stale coordinates after a failed signing submission;
  • allow the existing retry flow to collect fresh coordinates when needed.

The frontend must not:

  • detect the client IP;
  • parse proxy headers;
  • perform GeoIP lookup;
  • call MaxMind;
  • call another GeoIP service;
  • submit IP-derived location;
  • submit source IP.

IP geolocation collection is entirely server-side.

GeoIP administration settings

Add the instance-level GeoIP database configuration provided by #8086.

Use:

  • GET /api/v1/admin/geoip
  • POST /api/v1/admin/geoip

Show this UI only to administrators. Backend authorization remains authoritative.

Allow administrators to:

  • view the configured database path;
  • set a database path;
  • replace the configured path;
  • clear the configuration.

An empty path clears the configuration.

Allow saving a path even when the file is not currently available.

This supports deployments where the database may later be provided through a container mount or another deployment mechanism.

The frontend must not validate or open the database itself.

The backend response is the source of truth for database state.

Database states

Handle:

  • not_configured
  • not_found
  • not_readable
  • invalid_database
  • unsupported_database
  • ready

Use clear user-facing labels and messages.

Do not use the raw enum value as the complete user message.

When available, also show:

  • database type;
  • database build time;
  • file modification time.

Do not expose:

  • backend exceptions;
  • stack traces;
  • internal diagnostic details;
  • signer IP addresses;
  • signer geolocation data.

GeoIP configuration problems are not signing failures and must not be presented as such.

Signed PDF Document Validation view

The Document Validation view must display stored geolocation evidence inside the existing signer details for each signer that has geolocation evidence.

This is historical evidence from the signature request and must come from the backend validation or audit response.

Use one Signer geolocation section inside the signer details.

Keep the two sources clearly separated.

Example:

Signer geolocation

Device-reported location
  Latitude
  Longitude
  Accuracy
  Collected at
  Physical presence not verified

IP-based approximate location
  Source IP
  Country
  Region
  City
  Latitude / longitude
  Accuracy radius

Reuse the existing geolocation presentation introduced by #8085 where practical, including existing collapsible patterns.

Device-reported location

When geolocation.device exists, show the available stored fields supported by the backend contract.

This may include:

  • latitude;
  • longitude;
  • accuracy;
  • timestamp.

Keep the existing explanation that device-reported location does not verify physical presence.

Do not display fields that are absent.

IP-based approximate location

When:

geolocation.ip.status = resolved

show the available stored fields, such as:

  • source IP;
  • country;
  • region;
  • city;
  • latitude;
  • longitude;
  • accuracy radius.

Only display fields actually returned by the backend.

Do not infer or reconstruct missing values.

When coordinates and accuracyRadius are available, display the accuracy radius together with the coordinates.

Clearly identify this source as approximate location derived from the signer IP address.

Do not describe it as:

  • verified location;
  • exact location;
  • physical presence;
  • signer address.
GeoIP not found

When:

geolocation.ip.status = not_found

show a short indication that no approximate location was found.

If sourceIp is returned by the backend, it may be displayed with this state.

This must not make the signature appear invalid or failed.

GeoIP unavailable

When:

geolocation.ip.status = unavailable

show a short indication that IP-based location was unavailable when the signer signed.

The frontend should use the backend reason to select an appropriate translated message for:

  • database_not_ready
  • address_unavailable
  • lookup_failed

Do not show raw enum values when a user-facing message is available.

If sourceIp is returned by the backend, it may be displayed with this state.

This state must not make the signature appear invalid or failed.

GeoIP not collected

If geolocation.ip is absent, do not show a GeoIP error.

The source may simply not have been enabled for that signature request.

Multiple sources

Device and IP geolocation may both exist for the same signer.

When both exist:

  • show both;
  • identify each source clearly;
  • do not merge coordinates;
  • do not calculate an average location;
  • do not compare the locations automatically;
  • do not show a match or mismatch result;
  • do not rank one source as more authoritative.

Document Validation presents stored evidence. It does not interpret whether the two location sources agree.

Historical behavior

Stored geolocation must remain visible independently of current policy values.

Example:

  1. IP geolocation is enabled;
  2. a signature request is created;
  3. the signer signs and GeoIP evidence is stored;
  4. the effective IP geolocation policy is later disabled;
  5. Document Validation must still show the stored GeoIP evidence.

Likewise, enabling IP geolocation later must not add an IP section to an older signed request that did not collect it.

Stored signer metadata is authoritative for historical validation.

Data exposure and authorization

Use only the geolocation fields exposed by the backend audit and validation APIs.

Do not request or expose the complete internal SignRequest.metadata object.

Geolocation data must follow the same authorization and visibility rules already used for signer information in Document Validation.

Do not introduce a separate frontend fetch path that bypasses the existing authorization model to retrieve signer IP addresses or geolocation data.

The GeoIP administration area must expose configuration and database status only.

It must never expose signer data.

Accessibility

Follow existing LibreSign and Nextcloud component patterns.

At minimum:

  • controls must be keyboard accessible;
  • policy controls must have accessible names;
  • status information must not depend only on color;
  • collapsible sections must expose expanded/collapsed state;
  • device and IP source labels must be understandable without relying only on icons;
  • GeoIP configuration and validation states must be available to assistive technology.

Screenshots

This issue changes user-visible interfaces.

The implementation PR must include screenshots showing the relevant final UI states.

At minimum, include screenshots for:

  • the Signer geolocation section in the Policy Workbench with device and IP policies;
  • the GeoIP administration settings with a configured database;
  • at least one non-ready GeoIP database state when that state changes the visible UI;
  • the requester flow when device geolocation is optional or required;
  • the signed PDF Document Validation view with device geolocation;
  • the signed PDF Document Validation view with IP geolocation;
  • the validation view with both sources when both are available.

Screenshots should use realistic test data and must not contain real signer IP addresses or other personal data.

If the affected UI already has automated screenshot or visual-regression coverage, update the corresponding fixtures and expected screenshots.

Do not add a new visual-regression framework only for this issue.

Tests

Use mocked backend responses for focused frontend unit and component tests.

Do not reproduce backend policy resolution logic in frontend tests.

Policy Workbench tests

Cover:

  • signer_device_geolocation = disabled;
  • signer_device_geolocation = optional;
  • signer_device_geolocation = required;
  • signer_ip_geolocation = disabled;
  • signer_ip_geolocation = enabled;
  • both policies shown under the same signer geolocation area;
  • policies remain independent;
  • inherited values;
  • delegated values where applicable;
  • non-editable values;
  • GeoIP database path is not exposed as a group or user policy.
Request flow tests

Cover:

  • device policy disabled hides the per-signer control;
  • optional device policy allows deviceGeolocationRequired;
  • required device policy cannot be disabled per signer;
  • no per-signer control exists for IP geolocation;
  • existing request behavior comes from backend request data;
  • changing the current policy does not change existing request behavior;
  • unrelated edits preserve the frozen device requirement.
Signing flow tests

Keep or update coverage for:

  • required device geolocation;
  • information/privacy step before browser permission;
  • successful browser location collection;
  • permission denied;
  • unavailable location;
  • timeout;
  • retry behavior;
  • stale coordinates are not reused after a failed submit;
  • signing payload uses deviceGeolocation;
  • frontend never submits geolocation.ip;
  • frontend never submits GeoIP coordinates;
  • frontend never submits source IP.
GeoIP administration tests

Cover:

  • loading configuration;
  • saving a path;
  • replacing a path;
  • clearing configuration;
  • saving a path that is currently unavailable;
  • not_configured;
  • not_found;
  • not_readable;
  • invalid_database;
  • unsupported_database;
  • ready;
  • available database metadata;
  • signer data is not displayed in the admin settings area.
Document Validation tests

Cover:

  • signer with device geolocation only;
  • signer with IP geolocation only;
  • signer with both sources;
  • multiple signers with different available sources;
  • resolved GeoIP result;
  • partial resolved result with missing optional fields;
  • not_found;
  • unavailable;
  • absent geolocation.ip;
  • source IP display when returned;
  • coordinates with accuracy radius;
  • approximate-location wording;
  • historical geolocation remains visible after current policy changes;
  • enabling a policy later does not create evidence for an older request;
  • no automatic match/mismatch result;
  • no preferred or merged location.
API contract tests

Update frontend fixtures and types to the final #8086 contract.

Confirm the frontend uses:

  • signer_device_geolocation;
  • signer_ip_geolocation;
  • deviceGeolocationRequired;
  • deviceGeolocationRequirement;
  • deviceGeolocation;
  • geolocation.device;
  • geolocation.ip.

Do not keep compatibility handling for previous development names.

Playwright / E2E

Add focused E2E coverage for the complete visible flow where practical.

At minimum:

  1. use the GeoIP test database/configuration provided by the backend test environment;
  2. configure device and IP geolocation policies;
  3. create a signature request;
  4. confirm the expected requester controls;
  5. complete signing with device geolocation where required;
  6. use backend-controlled GeoIP test data;
  7. open the signed PDF Document Validation view;
  8. confirm device and IP evidence are shown as separate sources.

Also add a regression scenario for policy snapshot behavior:

  1. enable a geolocation source;
  2. create a signature request;
  3. change the current effective policy;
  4. confirm the existing request keeps the behavior returned by the backend;
  5. create a new request;
  6. confirm the new request uses the new effective policy.

Do not make frontend E2E tests depend on:

  • Internet access;
  • external GeoIP services;
  • a production GeoIP database;
  • real external location.

Quality gates

The implementation must pass the existing frontend checks:

  • Vitest;
  • TypeScript checks;
  • ESLint;
  • Stylelint where applicable;
  • Playwright/E2E tests;
  • generated OpenAPI TypeScript type checks.

Do not edit generated API types manually.

Regenerate them from the final OpenAPI contract from #8086.

Development-state compatibility

Signer geolocation has not been released yet.

Update the current frontend implementation directly to the final contract defined by #8086 and this issue.

Do not add:

  • aliases for previous development policy names;
  • fallback API field names;
  • compatibility branches for the current intermediate frontend;
  • tests whose only purpose is preserving an unreleased development contract.

There is only one intended frontend contract after this issue: the final contract defined here.

Done when

  • The frontend uses signer_device_geolocation and signer_ip_geolocation.
  • Device and IP policies are visually grouped but remain independent.
  • The current device geolocation frontend uses the final field names from #8086.
  • deviceGeolocationRequired is used only for requester device-location selection.
  • Existing requests use backend-provided frozen behavior instead of current Policy Workbench values.
  • Policy changes affect new requests without changing existing requests.
  • Signing submits device location only through deviceGeolocation.
  • The frontend never submits IP geolocation data or source IP.
  • Administrators can configure and clear the local GeoIP database path.
  • All GeoIP database states defined by #8086 have clear frontend handling.
  • GeoIP database validation remains backend-only.
  • The GeoIP settings area never exposes signer data.
  • Stored device geolocation is displayed in signed PDF Document Validation.
  • Stored IP geolocation is displayed in signed PDF Document Validation.
  • Each signer shows only the geolocation evidence actually stored for that signer.
  • Device and IP sources remain clearly separated.
  • IP-derived location is clearly presented as approximate.
  • Available accuracy radius is displayed with IP coordinates.
  • not_found and unavailable GeoIP states do not make the signature appear invalid.
  • Historical geolocation remains visible after later policy changes.
  • The UI does not merge, rank or automatically compare location sources.
  • Existing signer authorization rules are reused for geolocation display.
  • Generated TypeScript types use the final #8086 OpenAPI contract.
  • Previous unreleased development names are not kept as compatibility aliases.
  • The implementation PR includes screenshots of the main changed UI states.
  • Existing automated screenshot or visual-regression coverage is updated when applicable.
  • Unit/component and Playwright tests cover the final frontend behavior.

Out of scope

This issue does not implement:

  • GeoIP lookup;
  • GeoIP database parsing or validation;
  • backend policy resolution;
  • backend policy snapshot persistence;
  • backend signer metadata persistence;
  • client-side IP detection;
  • client-side GeoIP lookup;
  • external GeoIP services;
  • GeoIP database upload;
  • automatic GeoIP database download or update;
  • map visualization;
  • comparison rules between device and IP locations;
  • match/mismatch detection;
  • fraud or risk scoring;
  • automatic decisions based on geolocation;
  • a third master geolocation policy;
  • compatibility support only for intermediate unreleased frontend states;
  • a new visual-regression framework only for this feature.

Backend support is defined by #8086.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.