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
6 changes: 5 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ on:
- '.github/workflows/docs.yml'
- '.github/workflows/deploy.yml'
- 'versioning/**'
- 'versioned/**'
- 'AGENTS.md'
- 'CONTRIBUTING.md'
- 'README.rst'
- 'README.md'
- 'docs/maintainers/**'
- 'assets/**'
- '_templates/**'
- 'main/**'
Expand Down
25 changes: 24 additions & 1 deletion .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,29 @@ jobs:
qr-code: false
token: ${{ steps.preview-token.outputs.token }}

- name: Wait until GitHub Pages serves this exact preview revision
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: |
# The deploy action pushes gh-pages, but Pages publishes it
# asynchronously. Byte equality of versions.json proves the
# exact documentation revision has reached the public origin.
for attempt in $(seq 1 108); do
if curl -fsSL --max-time 15 -H 'Cache-Control: no-cache' \
-o /tmp/libresign-live-versions.json \
"$PREVIEW_ROOT/versions.json?run=$GITHUB_RUN_ID&attempt=$attempt" &&
cmp -s _publish/versions.json /tmp/libresign-live-versions.json; then
echo "GitHub Pages serves the expected documentation revision"
break
fi
if [ "$attempt" -eq 108 ]; then
echo "::error::GitHub Pages did not publish this preview revision" >&2
exit 1
fi
sleep 10
done

- name: Check every navigable preview route on the public origin
if: github.event.pull_request.head.repo.full_name == github.repository
env:
Expand All @@ -121,7 +144,7 @@ jobs:
fi
url="$PREVIEW_ROOT$route"
success=false
for attempt in $(seq 1 24); do
for attempt in $(seq 1 4); do
if curl -fsSL --max-time 15 -H 'Cache-Control: no-cache' \
-o /tmp/libresign-preview-page.html \
"$url?run=$GITHUB_RUN_ID&attempt=$attempt" &&
Expand Down
34 changes: 17 additions & 17 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,18 @@ configuration instruction, rendered example, or troubleshooting step:
Check nested required request fields, types/enums, responses, authentication,
feature availability, signing state and error cases. OpenAPI shape alone
does not prove runtime behavior; the presence of a test is not proof it ran.
3. **Choose the source scope deliberately.** `developer_manual/` is the
development line. `versioned/base/` is for behavior verified in **every**
published stable line; `versioned/<major>/` overrides it when any stable
behavior differs. The `main/` directory contains site navigation, not the
development developer manual. Never copy development-only claims into the
stable base, or assume newer features were backported. For an unverified
release, omit or explicitly qualify the claim rather than invent support.
3. **Choose the release branch deliberately.** The `main` branch is
development; `stableNN` contains the complete documentation for LibreSign
major NN. Do not mix Nextcloud major numbers with LibreSign major numbers.
Changes to multiple versions require explicit backports and verification
against the corresponding application contract.
4. **Verify executable examples per release.** Use the correct version-specific
fixtures and checks; never make older guides silently use a newer payload.
Add regression coverage for incompatibilities, including negative cases.
Do not weaken a contract check just to keep inherited prose passing.
For ordinary RST pages, do not add Python tests that enumerate page paths,
assert editorial wording or mirror the documentation tree. The existing
Sphinx, link, OpenAPI and multiversion build checks validate those changes.
Add focused regression coverage only when executable contracts or the
documentation tooling itself change. Do not weaken existing contract checks.
5. **Review versioned links and surrounding pages.** Avoid silently linking
older manuals to `/main/`, `/latest/`, or moving source-branch URLs when
claiming version-specific support. Inspect related pages across all three
Expand All @@ -65,14 +66,13 @@ configuration instruction, rendered example, or troubleshooting step:
scenarios, and behaviors are verified versus untested. Green Sphinx/CI
checks are not proof of real signing, SMTP, policies, or file permissions.

This repository builds stable versions from `versioned/base/` plus overlays,
not from separate documentation branches as Nextcloud does. Directory scopes
shared from the development manual into stable builds are declared in
`versioned/shared.json`, never hardcoded per page in build scripts. Preserve the
existing dynamic discovery and build infrastructure. For authoring details
and the external-email-signers fixture conventions, read
[CONTRIBUTING.md](CONTRIBUTING.md). Application behavior and API contract
changes belong in `LibreSign/libresign` and require a separate change there.
Each release branch contains complete `main/`, `user_manual/`, `admin_manual/`
and `developer_manual/` source directories. There is no `versioned/base` or
per-file overlay mechanism. The central publishing tool checks out the exact
documentation branch and pins the application OpenAPI separately. A missing
stable documentation branch must fail rather than inherit development prose.
For authoring instructions read [CONTRIBUTING.md](CONTRIBUTING.md).
Application source and API changes belong to `LibreSign/libresign`.

## Quality gates

Expand Down
165 changes: 60 additions & 105 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,117 +1,72 @@
<!--
SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
SPDX-License-Identifier: CC-BY-3.0
-->
<!-- SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
SPDX-License-Identifier: CC-BY-3.0 -->

# Contributing to LibreSign documentation

This repository contains LibreSign's public user, administrator, and developer
documentation. Choose the manual for your reader: `user_manual/`,
`admin_manual/`, or `developer_manual/`. The `main/` directory provides
top-level navigation. Follow the existing manual structure and write about the
product or procedure, not the history of implementing a change. Explain concepts
before advanced details, link to existing explanations instead of duplicating
them, verify internal links and cross-references, and use examples without real
personal or customer data.
You can edit the documentation without knowing Python or the site generator.

## Build and review your change
## Select a version

From the repository root, install Python 3.13 and the dependencies from the root
`requirements.txt` in a virtual environment. For example:
The branch **is** the LibreSign documentation version:

| Branch | Documentation |
| --- | --- |
| `main` | Next LibreSign release (development) |
| `stable15` | LibreSign 15 |
| `stable14` | LibreSign 14 |
| `stable13` | LibreSign 13 |

New releases follow `stableNN`, where `NN` is the **LibreSign** major, not
Nextcloud's major. The published version selector and **Edit on GitHub** links
should take you to the matching branch automatically.

## Edit one page

1. Open the version and manual you want to change at https://docs.libresign.coop.
2. Select **Edit on GitHub** or browse the corresponding branch.
3. Edit the RST file under `user_manual/`, `admin_manual/` or `developer_manual/`.
4. For a new page, add its name to the section `index.rst` (`.. toctree::`).
5. Create a pull request targeting the **same** branch.
6. Review the HTML preview and fix any Sphinx warnings or broken links.

**No Python test, manual file manifest, or generator change is needed to add a
page.** The CI builds the manual and checks internal links automatically.

## Make a fix available in multiple versions

Correct the newest applicable version first. Backport the same change to each
older `stableNN` branch that needs it (one PR per target branch). Do not assume
that an API operation or configuration option is available in an older release.

API examples must match the pinned application OpenAPI and implementation for
the intended LibreSign version. The documentation builds use the application
manifest and the exact application commit; a Nextcloud version or an OCS
`/api/v1` URL does not establish feature compatibility.

## Preview locally

Install Python and the dependencies in a virtual environment, then run:

```sh
python -m venv .venv
# Activate .venv for your shell, then:
python -m pip install -r requirements.txt
sphinx-build -n -W developer_manual _build/developer_manual
```

Build every manual whose rendered pages you changed before opening a pull
request. The root `Makefile` provides `make main`, `make user`, `make admin`,
`make dev`, and `make all`. If `make` is unavailable, use the same Sphinx commands
as the [Documentation CI workflow](.github/workflows/docs.yml):
Replace `developer_manual` with the manual you changed. The PR workflow also
validates all published releases, API provenance, SEO and links.

```sh
sphinx-build main _build/main
sphinx-build user_manual _build/user_manual
sphinx-build admin_manual _build/admin_manual
sphinx-build -W developer_manual _build/developer_manual
```
Do not rename published pages without preserving their URLs with redirects.
Never put credentials or real customer data into examples.

## New stable LibreSign release

The maintainers create `stableNN` from the approved development (`main`) manual
when the LibreSign application releases that major. Public versions are
discovered from the application manifest, not a hardcoded list in the site.
The branch must exist before the documentation build can publish that release.

## Commit policy

Run the affected command(s), not necessarily all four; CI builds every
version. For stable or cross-version edits, run
`python -m versioning.build --output _build` when network access is available;
it uses pinned application contracts. The developer manual is built with
warnings treated as errors. The PR workflow publishes a navigable preview
for visual checking of headings, code blocks, links and layout. No
screenshot attachment or Python change is required to add an RST page.

## Version-scoped integration documentation

The published version selector does not by itself make prose compatible with
an older LibreSign release. The build discovers application releases from
`appinfo/info.xml`, pins each source commit and publishes that commit's
`openapi.json`. The exact LibreSign/Nextcloud versions are available in
Sphinx as `|LibreSignRelease|` and `|NextcloudRelease|`.

The source layout deliberately has three different scopes:

- `developer_manual/` describes the development (`main`) application.
- `versioned/base/` contains only claims verified across the published
stable releases. Do not copy development-only behavior into this base.
- `versioned/<major>/` overrides stable content when a release differs.
- `versioned/shared.json` lists **directory scopes**, not individual pages,
that are already verified as release-safe and can be copied from the
development manual into stable builds. New RST files inside a declared
section are included automatically. Add a new directory to this small
declarative file only when all relevant stable releases support its content.
Keep development-only pages outside shared scopes.

Use `.. toctree::` in your RST section index so Sphinx can discover the
new page. No Python file needs modification to add a page, section or
version-specific override; keep release discovery dynamic.

For the external-email-signers guide, each supported application line has
a reviewed `examples/external-email-signers/request-<slug>.json` and a
`_external-email-signers-release.inc` in its own source directory.
The Sphinx include extension `.inc` prevents these snippets from being
treated as additional standalone manual pages. The CLI clients refuse
to choose a fixture implicitly: `LIBRESIGN_DOC_LINE` selects a reviewed
release explicitly. When a new release is discovered, add its reviewed
fixture and overlay rather than inheriting an older identity schema.

The Documentation CI gate validates the actual nested request fields
and example JSON against **that version's pinned OpenAPI**, checks
guarded controller and Playwright source files from the **same pinned
application commit**, and rejects unknown/new releases without reviewed
examples. It does not assert that browser signing, SMTP or certificate
verification passed in a live environment. Record those executions
separately when performed. Changes to an API contract must be made in
the LibreSign application repository and regenerated there; do not
modify the pinned JSON inside the documentation repository.

## Pull request preview and evidence

Link the relevant issue and describe the affected versions. The workflow
publishes the complete multiversion HTML preview on an isolated origin and
checks its public URLs. Review the rendered result by opening its links:
navigation, responsive layout, dark mode, code blocks and cross-references
are easier to verify there than in static screenshots. No screenshots are
required, and you do not need to edit Python for ordinary RST contributions.

Documentation for an unreleased application major is rendered into a separate
`/_review/` preview area, with direct links in a PR comment. It does not
appear in production Pages or the published version selector. Future-release
content uses development application metadata for preview, not an invented
stable OpenAPI. Contributor fork previews use the same isolated static HTML
site, deployed by a privileged workflow that does not execute fork code.

Keep each pull request focused. Report the tests actually run and any known
runtime coverage gaps; never include secrets, private documents or real
customer data in examples or previews.

## Developer Certificate of Origin

Sign off each commit to certify the [Developer Certificate of Origin](https://developercertificate.org/).
With your Git name and email configured, use `git commit -s -m "Your message"`.
The resulting `Signed-off-by: Name <email>` trailer must identify you; use an
email associated with your GitHub account if you want GitHub to attribute it.
Sign off every commit according to the
[Developer Certificate of Origin](https://developercertificate.org/).
A GitHub verified signature is also required when enforced by the repository.
52 changes: 30 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
<!--
SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
SPDX-License-Identifier: CC-BY-3.0
-->
<!-- SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
SPDX-License-Identifier: CC-BY-3.0 -->

# LibreSign documentation

Source for the [LibreSign public documentation](https://docs.libresign.coop/),
built with Sphinx. The site provides separate manuals for stable LibreSign
majors (`/13/`, `/14/`, `/15/`) and development (`/main/`).

- **Edit content:** use RST in `developer_manual/`, `user_manual/` or
`admin_manual/`. The `versioned/base/` directory holds stable foundations;
`versioned/<major>/` holds overrides. Shared development-to-stable sections
are listed in `versioned/shared.json`. Adding a page never requires editing
Python build or screenshot scripts.
- **Contribute:** open a PR. CI checks Sphinx, links, OpenAPI provenance and
version isolation. Review the navigable preview, including any unpublished
release pages under `/_review/`; screenshots are not required.
- **Maintain releases:** see the
[maintainer guide](docs/maintainers/versioning.md) for local builds,
deployment, previews, backports and lifecycle metadata.

Canonical release history and API sources remain in
[LibreSign/libresign](https://github.com/LibreSign/libresign).
Public manuals: **https://docs.libresign.coop**.

The documentation follows Nextcloud's **one branch per version** pattern:

| Branch | LibreSign documentation |
| --- | --- |
| `main` | Next release, in development |
| `stable15` | LibreSign 15 |
| `stable14` | LibreSign 14 |
| `stable13` | LibreSign 13 |

For a new release, use `stableNN`, where NN is the **LibreSign major** (not the
Nextcloud server major). Each branch contains complete `user_manual/`,
`admin_manual/` and `developer_manual/` sources. There are no `versioned/`
source overlays and no per-page Python tests to update.

**To edit a page:** choose the LibreSign version on the website, select
**Edit on GitHub**, update the RST file and open a PR to the **same branch**.
For a new page, add it to the section's `index.rst` (`.. toctree::`).
For changes applying to multiple versions, backport explicitly.

See [CONTRIBUTING.md](CONTRIBUTING.md) for everyday editing and
[docs/maintainers/versioning.md](docs/maintainers/versioning.md) for the
publication process, API contracts and new releases.

The build dynamically discovers released LibreSign majors and pins their
OpenAPI contracts to their exact application commits. Releases are never
inferred from a documentation branch alone.
Loading
Loading