LibreSign / LibreSign/libresign
Finalize signer geolocation frontend with IP-based location
@lfals is already working on this.
Since Sep 11, 2026.
- 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:
disabledoptionalrequired
IP policy
Add:
signer_ip_geolocation
Supported values:
disabledenabled
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
deviceGeolocationRequirementduring 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/geoipPOST /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_configurednot_foundnot_readableinvalid_databaseunsupported_databaseready
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_readyaddress_unavailablelookup_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:
- IP geolocation is enabled;
- a signature request is created;
- the signer signs and GeoIP evidence is stored;
- the effective IP geolocation policy is later disabled;
- 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:
- use the GeoIP test database/configuration provided by the backend test environment;
- configure device and IP geolocation policies;
- create a signature request;
- confirm the expected requester controls;
- complete signing with device geolocation where required;
- use backend-controlled GeoIP test data;
- open the signed PDF Document Validation view;
- confirm device and IP evidence are shown as separate sources.
Also add a regression scenario for policy snapshot behavior:
- enable a geolocation source;
- create a signature request;
- change the current effective policy;
- confirm the existing request keeps the behavior returned by the backend;
- create a new request;
- 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_geolocationandsigner_ip_geolocation. - Device and IP policies are visually grouped but remain independent.
- The current device geolocation frontend uses the final field names from #8086.
-
deviceGeolocationRequiredis 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_foundandunavailableGeoIP 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.