Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,33 +89,54 @@ jobs:
deploy-repository: LibreSign/site-preview
preview-branch: gh-pages
pages-base-url: libresign.github.io/site-preview
wait-for-pages-deployment: true
qr-code: true
# A newer deployment from another PR can supersede this Pages build.
# Verify our published revision over HTTP instead of waiting on its run ID.
wait-for-pages-deployment: false
comment: false
qr-code: false
token: ${{ steps.preview-token.outputs.token }}

- name: Check every navigable preview route on the public origin
if: github.event.pull_request.head.repo.full_name == github.repository
env:
PREVIEW_ROOT: https://libresign.github.io/site-preview/docs-preview/pr-${{ github.event.pull_request.number }}
run: |
while IFS= read -r route; do
# GitHub Pages is shared with other PR previews. Its deployment run
# can be superseded even when this preview's HTML is publicly served.
# Compare rendered pages with the public origin instead of a specific
# Pages run or PR merge SHA.
{
cat _publish/_review/routes.txt
find _publish -type f -name '*.html' -printf '/%P\n'
printf '%s\n' '/home.css' '/home-theme.js' '/versions.json'
} | sort -u | while IFS= read -r route; do
[ -n "$route" ] || continue
local_page="_publish$route"
if [[ "$route" == */ ]]; then
local_page="${local_page}index.html"
fi
if [ ! -f "$local_page" ]; then
echo "::error::Missing generated preview page: $local_page" >&2
exit 1
fi
url="$PREVIEW_ROOT$route"
success=false
for attempt in $(seq 1 24); do
if curl -fsSL --max-time 15 -o /tmp/libresign-preview-page.html "$url" &&
grep -Eq 'libresign-version-toggle|Documentation by release|Preview-only documentation' /tmp/libresign-preview-page.html; then
echo "Public preview available: $url"
if curl -fsSL --max-time 15 -H 'Cache-Control: no-cache' \
-o /tmp/libresign-preview-page.html \
"$url?run=$GITHUB_RUN_ID&attempt=$attempt" &&
cmp -s "$local_page" /tmp/libresign-preview-page.html; then
echo "Published preview matches generated content: $url"
success=true
break
fi
sleep 5
done
if [ "$success" != true ]; then
echo "::error::Preview page unavailable: $url" >&2
echo "::error::Public preview missing or stale: $url" >&2
exit 1
fi
done < _publish/_review/routes.txt
done

- name: Comment with navigable preview links
if: github.event.pull_request.head.repo.full_name == github.repository
Expand Down
12 changes: 12 additions & 0 deletions _templates/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ <h1>Find documentation for your version of LibreSign.</h1>
{% endfor %}
</p>
</div>
<section class="quick-tasks" aria-labelledby="quick-tasks-title">
<h2 id="quick-tasks-title">Find a task</h2>
<p>Start with the latest stable LibreSign {{ current_stable }} manual, or choose your
installed version below.</p>
<ul>
<li><a href="{{ current_stable }}/user_manual/start.html">Get started with signing</a></li>
<li><a href="{{ current_stable }}/user_manual/functionality.html">Request and track signatures</a></li>
<li><a href="{{ current_stable }}/user_manual/functionality.html">Validate a signed PDF</a></li>
<li><a href="{{ current_stable }}/admin_manual/installation.html">Install and configure LibreSign</a></li>
<li><a href="{{ current_stable }}/developer_manual/integration/index.html">Integrate another application</a></li>
</ul>
</section>
<section class="versions-section" aria-labelledby="versions-title">
<div class="section-heading">
<h2 id="versions-title">Available versions</h2>
Expand Down
20 changes: 20 additions & 0 deletions assets/home.css
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,26 @@ h1 {
.hero > p:not(.eyebrow) { font-size: 1.04rem; line-height: 1.7; color: var(--muted); }
.hero .latest-reference { margin-top: 22px; font-size: .96rem; color: var(--text); }
.latest-reference a { font-weight: 700; }
.quick-tasks {
margin: 0 0 46px;
padding: 24px 28px;
border: 1px solid var(--border);
border-radius: 7px;
background: var(--surface);
}
.quick-tasks p {
margin: 8px 0 16px;
color: var(--muted);
line-height: 1.5;
}
.quick-tasks ul {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
gap: 12px 24px;
margin: 0;
padding-left: 20px;
}
.quick-tasks a { font-weight: 550; }
.section-heading {
display: flex;
flex-wrap: wrap;
Expand Down
15 changes: 0 additions & 15 deletions tests/test_seo.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,6 @@ def page(self, name: str, body: str = "<h1>Article</h1>"):
f"<body>{body}</body></html>", encoding="utf-8")
return path

def test_historic_routes_cover_all_existing_manual_pages(self):
root = Path(__file__).resolve().parent.parent
routes = read_legacy_routes(root)
source = {f"{manual}/{p.relative_to(root / manual).with_suffix('.html')}"
for manual in ("user_manual", "admin_manual", "developer_manual")
for p in (root / manual).rglob("*.rst")}
self.assertEqual(set(routes), source)
self.assertEqual(len(routes), 46)
self.assertEqual(routes["user_manual/functionality.html"],
"main/user_manual/functionality.html")
self.assertEqual(routes["admin_manual/installation.html"],
"main/admin_manual/installation.html")
self.assertEqual(routes["developer_manual/architecture.html"],
"main/developer_manual/architecture.html")

def test_legacy_redirects_keep_individual_targets_across_new_stable(self):
self.page("15/index.html")
for name in ("15/user_manual/index.html",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def test_preview_review_link_is_valid_during_initial_site_verification(self):
(root / filename).write_text("asset")
with patch.dict("os.environ", {"LIBRESIGN_PREVIEW_PR": "127"}):
legacy_redirects(root, "15", routes={})
self.assertEqual(inspect_links(root, root / "index.html"), [])
self.assertIn('href="_review/"', (root / "index.html").read_text())
self.assertTrue((root / "_review/index.html").is_file())

def test_production_does_not_create_review_page(self):
Expand Down
36 changes: 36 additions & 0 deletions versioned/base/admin_manual/configuration.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Configure signing
=================

Open **Administration settings** in Nextcloud and find LibreSign. Configuration
is server-owned: users should not be asked to change a system-wide signing
policy to complete a single request.

Signing and identity
--------------------

Review the available signature engine and signing methods before enabling
external signers. The user's available choices can depend on permissions,
identity methods, and policy settings. Test the configured invitation method
with a non-production request before relying on it.

The administrative layout changes across supported releases. In LibreSign 13
and 14, several settings appear as individual controls; LibreSign 15 includes
the Policy Workbench for applicable configuration. Consult the visible
controls in your installed version rather than looking for an identically
named control in every release.

Certificates and dependencies
-----------------------------

- Review **Certificate engine** and **Root certificate data** and the chosen
trust model before issuing signatures.
- Use **Configuration check** and the **Dependencies** section to diagnose
an incomplete installation.
- Record the selected certificate policy and secure storage location as part
of your deployment's operational documentation.

Changing a trust anchor or regenerating a root certificate is not routine
configuration. See :doc:`security` and :doc:`maintenance` first.

For integration and version-pinned API payloads, use the
`developer API reference <../developer_manual/api/index.html>`_.
33 changes: 22 additions & 11 deletions versioned/base/admin_manual/index.rst
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
Administrator manual — LibreSign |LibreSignRelease|
===================================================

The LibreSign |LibreSignRelease| line requires a compatible Nextcloud
|NextcloudRelease| instance, as declared by its application manifest.
This manual covers LibreSign |LibreSignRelease| for Nextcloud
|NextcloudRelease|. Check the matching app release before changing server
settings or restoring data. Procedures are limited to the stable versions
listed in the documentation version selector.

Install or upgrade the application version compatible with your Nextcloud
release, and inspect the application configuration in the Nextcloud
administration interface. Before upgrading, consult the release notes in
`LibreSign/libresign <https://github.com/LibreSign/libresign/releases>`_.
Choose an operation
-------------------

This manual intentionally omits unverified configuration steps from
the development branch. Version-specific operational guides can be
added here without changing other published release lines.
- :doc:`installation` — install LibreSign and complete initial setup.
- :doc:`configuration` — find the signing and certificate configuration.
- :doc:`maintenance` — back up, upgrade, and troubleshoot an installation.
- :doc:`security` — protect signing credentials and review security choices.

For support-lifecycle information see the
`release lifecycle guide <../lifecycle.html>`_.
For the signing experience, see the `user manual
<../user_manual/index.html>`_; for API authentication and integration,
consult the `developer manual <../developer_manual/index.html>`_.

.. toctree::
:maxdepth: 2
:caption: Operations

installation
configuration
maintenance
security
41 changes: 41 additions & 0 deletions versioned/base/admin_manual/installation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Install and initialize LibreSign
================================

Prerequisites
-------------

Use a supported Nextcloud instance and the matching LibreSign release. The
application declares compatibility in its ``appinfo/info.xml``; this site's
release selector distinguishes LibreSign versions from Nextcloud versions.
Use an administrator account and plan for adequate disk space and network
access if the application must download signing dependencies.

Install the app
---------------

#. Open Nextcloud's **Apps** administration page.
#. Search for **LibreSign** and install or enable the release offered for
your compatible Nextcloud version.
#. Open the LibreSign administration settings and inspect **Configuration
check** for resources requiring attention.
#. In **Dependencies**, use **Download binaries** if prompted, then
**Validate setup** to check the installation. The operation can take time
and requires server resources.
#. Configure the certificate engine and the **Root certificate data**
appropriate to your organization. For the OpenSSL engine, the root
certificate form asks for a **Common Name (CN)** and allows generating a
root certificate when the installation requires it.
#. Resolve remaining configuration errors before sending real invitations.

The location and presentation of some settings differ between LibreSign
releases; see :doc:`configuration`. Do not regenerate an existing production
root certificate merely to repeat initial setup.

Check the installation
----------------------

Open LibreSign with a permitted user account. In a test environment, create
a request, complete its supported signing method, and open **Validate
signature** on the result. A successful installation check is not equivalent
to verifying mail delivery, external identity providers, or production
certificate policy; exercise those separately when enabled.
37 changes: 37 additions & 0 deletions versioned/base/admin_manual/maintenance.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Maintain an installation
========================

Before upgrading
----------------

#. Confirm the target LibreSign release is compatible with the installed
Nextcloud version; do not assume matching numbers refer to the same product.
#. Record the current application and Nextcloud versions, configuration,
certificate engine, and enabled signing or identification methods.
#. Back up the Nextcloud database, configuration, related files, and the
certificate material and signing keys required by your deployment.
Protect these backups according to their sensitivity.
#. Follow Nextcloud's supported application upgrade procedure and consult
the `LibreSign releases <https://github.com/LibreSign/libresign/releases>`_
for changes relevant to your target version.
#. Check **Configuration check** after the upgrade; perform a test signing
and validate its resulting PDF before resuming production activity.

Backups must be recoverable: verify recovery on an isolated system, including
access to the certificate material necessary for previously signed documents.
Do not expose private keys in tickets, logs, or example configurations.

Troubleshooting
---------------

- **Cannot request a signature:** check the user's permissions and the
allowed identification methods in :doc:`configuration`.
- **Setup is incomplete:** inspect **Configuration check** and
**Dependencies**, and check Nextcloud's application logs.
- **An invitation was not received:** verify the request status and the
configured delivery channel; inspect the mail system only if email delivery
is configured. Avoid resending invitations blindly.
- **Validation fails:** inspect the reported certificate or PDF error, and
confirm that the signing environment's trust material is still available.

Do not regenerate the root certificate as a generic troubleshooting step.
38 changes: 38 additions & 0 deletions versioned/base/admin_manual/security.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Security and trust
==================

Protect signing credentials
---------------------------

Restrict administrator access to certificate configuration and any signing
keys. Protect backups and limit access to credentials; do not copy private
keys into public reports or screenshots. Keep Nextcloud, LibreSign, and the
underlying TLS configuration maintained.

Certificate lifecycle
---------------------

LibreSign's **Root certificate data** interface provides a root certificate
configuration. The OpenSSL engine explicitly warns that **Regenerate root
certificate** invalidates existing signing keys. Treat regeneration as a
planned key lifecycle or recovery operation, not as ordinary maintenance.
Prepare and test a recovery and validation plan before changing a trust
anchor used by existing documents.

Signers and access
------------------

Review which accounts may create requests and which identification methods
are available to external signers. A signing invitation is sensitive: avoid
publishing the link or including it in a public issue. Test the separation
between request owner, intended signer, and unrelated users when configuring
external access.

Validation and compliance
-------------------------

Provide recipients with a way to validate signed PDFs. Technical signature
validation and certificate status do not by themselves prove legal compliance
in every jurisdiction or that a signer's identity was established to a
particular assurance level. Document applicable organizational rules
separately from the application's cryptographic capabilities.
27 changes: 21 additions & 6 deletions versioned/base/developer_manual/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,32 @@ Developer manual — LibreSign |LibreSignRelease|
===============================================

This is the **release-specific API contract** for LibreSign
|LibreSignRelease| and Nextcloud |NextcloudRelease|.
|LibreSignRelease| and Nextcloud |NextcloudRelease|. The schema is pinned
to an application commit on the corresponding stable branch. Development-only
API calls and payloads are not presented as features of this release.

The schema is pinned to an application commit on the corresponding stable
branch. API calls and payloads available only in the development branch
are not presented as features of this release.
Integrate an external application
---------------------------------

For supported integration strategies, see the architecture decision guides;
for executable API requests, use the release-specific email signer guide.
- :doc:`integration/index` — choose an integration architecture for an
existing application.
- :doc:`api/external-email-signers` — follow a release-specific API example
for inviting an external email signer.
- :doc:`api/openapi` — inspect the OpenAPI schema pinned to this release.

Contribute or develop LibreSign
-------------------------------

Source architecture, coding standards, development environment, tests, and
release engineering follow the project's current development branch. They
are available in the `development and contributor manual
<../../main/developer_manual/index.html>`_. That manual may describe
unreleased functionality. For integrating with LibreSign |LibreSignRelease|,
continue to use the version-specific reference above.

.. toctree::
:maxdepth: 2
:caption: Release-specific integration

api/index
integration/index
Loading
Loading