Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2258162
fix(installer): repair and complete the template store after an update
claude Sep 24, 2026
5f973d4
test(panels): pin PasarGuard and Rebecca support to what the installe…
claude Sep 24, 2026
926b172
docs: release notes for 1.2.1 and verify's new behaviour
claude Sep 24, 2026
9822b6c
Merge v1.2.1 template-store fixes into the v1.3.0 line
iitzSeriZ Sep 25, 2026
114bdcd
fix(rollback): restore backups the template store cannot identify
iitzSeriZ Sep 25, 2026
ddc5653
fix(release): write checksums in the text form on every platform
iitzSeriZ Sep 25, 2026
0f1fb2c
feat(shells): render PasarGuard and Rebecca pages from their real con…
iitzSeriZ Sep 25, 2026
0a623e6
feat(installer): support PasarGuard and Rebecca end to end
iitzSeriZ Sep 25, 2026
0b3d5f5
feat(templates): add Meter and Notebook, ported from the author's Pul…
iitzSeriZ Sep 25, 2026
21f0f7e
feat(pasarguard): report the database settings that outrank the page;…
iitzSeriZ Sep 25, 2026
cb0232b
fix(transaction): report a verified rollback as ROLLED_BACK
iitzSeriZ Sep 26, 2026
2ae89f5
docs: describe 1.3.0 — PasarGuard, Rebecca, Meter and Notebook
iitzSeriZ Sep 26, 2026
ec25bf3
release: prepare v1.3.0
iitzSeriZ Sep 26, 2026
cdd151a
fix(backup): two backups in the same second no longer share a directory
iitzSeriZ Sep 26, 2026
ea28150
docs(changelog): record the backup-collision and live-check fixes
iitzSeriZ Sep 26, 2026
3d89bff
fix(build): never truncate a build output in place
iitzSeriZ Sep 26, 2026
563136d
fix(rollback): restore an unrecognised backup page as the installed d…
iitzSeriZ Sep 26, 2026
0cd41d6
fix(rebecca): refuse the 0.0.x Python edition instead of failing sile…
iitzSeriZ Sep 26, 2026
5ae7434
docs: Rebecca support is Rebecca 1.x, the Go edition
iitzSeriZ Sep 26, 2026
0866c11
fix(install): run the panel preflight only for panels that have one
iitzSeriZ Sep 26, 2026
14be1e4
fix(installer): no pipe into grep -q or head can misreport a match
iitzSeriZ Sep 26, 2026
24245f8
style(backup): keep rt_backup_latest a bare one-liner
iitzSeriZ Sep 26, 2026
6926e32
style(backup): give rt_backup_latest its comment inside the body
iitzSeriZ Sep 26, 2026
87b7c7e
docs(changelog): record the structural-check fix
iitzSeriZ Sep 26, 2026
dd156f2
docs: state the upgrade limits of rollback and backup retention
iitzSeriZ Sep 26, 2026
ea71ca2
fix(activate): a failed panel refresh leaves sub.html as it was
iitzSeriZ Sep 26, 2026
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
242 changes: 239 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,240 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.0] - Unreleased
## [1.3.0] - 2026-09-26

Row-Template now installs on **PasarGuard** and **Rebecca** as well as 3X-UI,
and ships two more designs. A minor release: nothing changes for an existing
3X-UI install except what is listed below, and Row stays the default design.
It also carries every fix prepared for 1.2.1, which was not released on its
own.

### Added

- **PasarGuard support.** PasarGuard is supported from this release: detect,
install, activate, verify, back up, restore and uninstall, on the official
Docker install and on a source install (`pasarguard.service`). The page is
placed at `/var/lib/pasarguard/templates/row-template/index.html` (or inside
your own `CUSTOM_TEMPLATES_DIRECTORY`) and selected by one marked block
appended to `/opt/pasarguard/.env`; a running panel is restarted once. None
of your own `.env` lines is edited, and uninstall returns the file to its
exact previous bytes. `row-template verify` also reports the two panel
settings that still take precedence over the page: an admin's own
`sub_template`, and `disable_sub_template`.
- **Rebecca support.** Rebecca 1.x — the Go edition, which Rebecca publishes for
its binary install — is supported from this release, with the same seven
operations. The page is placed at
`/var/lib/rebecca/templates/row-template/index.html` (or inside your own
custom templates directory) and selected in the newest
`subscription_settings` row, which Rebecca reads on every request — so
nothing is ever restarted. Activation is automatic with the default SQLite
database and `sqlite3`; with MySQL/MariaDB the page is still placed and the
installer prints the two values to enter in the dashboard. `NULL`, empty and
a set templates directory are each restored exactly.
- **Panel detection and choice.** The installer finds the panel on the server
and installs for it (`/etc/3x-ui/sub_templates/row-template` for 3X-UI,
`/etc/row-template` for PasarGuard and Rebecca). A panel counts only when two
independent signals agree; a half-installed panel is refused, not guessed at.
On a server with more than one panel it asks, or reads
`RT_PANEL=3xui|pasarguard|rebecca` in a script.
- **Transactional activation on PasarGuard and Rebecca.** The panel's state is
snapshotted, changed and verified; if any step fails it is restored exactly,
and the installer says so — and shows the real cause.
- **Two new designs: Meter and Notebook.** Meter is a calm instrument
dashboard of rounded cards with a segmented traffic meter; Notebook is a
page from a dotted notebook, hand-inked. Both were contributed by the
project's author, ported onto the shared runtime, and held to the same
contract as the other fifteen — seventeen designs in all, on every panel.
- **Every design, for every panel.** Each release now carries a PasarGuard
(Jinja2) and a Rebecca (pongo2) page for every design, under `shells/`,
checksum-verified like the 3X-UI pages.

### Fixed

- **Rolling back to a backup taken under 1.1.0 works.** 1.2.x refused it with
"backup artifact matches no installed template". A backup that names its
design is restored as that design; one whose page is none of this release's
designs (1.1.0's) is restored as this release's Row, so `verify`, design
switching and updates keep working afterwards.
- **A successful rollback is reported as a success.** The transaction engine
checked, after restoring the panel, that the panel was still pointing at
Row-Template's directory — which is exactly the state a correct rollback has
just undone. Every rollback therefore ended in "the rollback failed" even
when the panel had been restored perfectly. The engine no longer asks that
question: the restore verifies itself. Each panel adapter now re-reads the
panel's own setting after restoring and confirms it matches the value it
recorded before changing anything, and a restore that does not land is
reported as a failed rollback with the real cause. A regression test pins
this: the engine must never re-run the forward check after a restore.
- **The manual PasarGuard instructions are complete.** When activation cannot
be done automatically, the installer printed only `SUBSCRIPTION_PAGE_TEMPLATE`
and told you to edit `.env` — but the page had not been copied anywhere the
panel could read. It now prints both the copy and the two `.env` values
(`CUSTOM_TEMPLATES_DIRECTORY` and `SUBSCRIPTION_PAGE_TEMPLATE`), and says to
keep your own templates directory if you already have one.
- **A rollback right after a change undoes that change.** Backup names have
one-second resolution, and two backups made in the same second — a design
switch followed at once by `row-template rollback --auto`, which snapshots
the current state first — shared one directory. The newer snapshot
overwrote the older one, so the rollback re-applied the state it was meant
to undo. A backup now waits for the next second rather than reuse a name.
- **The live check after `config`, `update` and `rollback` runs on 3X-UI.**
It always said "skipped (no test URL available without sqlite3)", even with
`sqlite3` installed, because those commands had not located the panel
database. And the check made right after activation no longer warns "could
not reach the subscription endpoint" while 3X-UI is still restarting.
- **A page change that cannot reach PasarGuard or Rebecca changes nothing.**
Regenerating the page (a rebrand, a design switch, an update) replaced
`sub.html` before copying it into the panel; if that copy failed, `sub.html`
was left newer than the page the panel serves. It is now put back.
- **A valid page is never refused under load.** The structural check before
every install, update and design switch read the page through
`head | grep -q`. On a busy server `grep -q` could stop reading before `head`
finished writing, and the shell then reported the match as a failure —
"generated template does not begin with <!doctype html>" for a perfectly
valid page, about once in 150 checks. Every such check is now written so
that it cannot be cut short.
- All fixes prepared for 1.2.1 (below): one `row-template update` is enough to
move from 1.1.0, misplaced designs are moved back, branding works on an
install the 1.1.0 updater left incomplete, and `verify` names missing and
damaged designs.

### Security

- **Every value is escaped on every panel.** PasarGuard renders pages with a
non-sandboxed Jinja2 whose autoescaping is off. Every PasarGuard and Rebecca
page therefore wraps its body in an explicit autoescape block, and is tested
with the panels' real engines against hostile usernames, notes, links and
malformed data.
- **Branding can never open a template tag.** `{` and `}` in your service name,
support link or logo are written as `{` and `}`, so no branding
value can start a Jinja2 or pongo2 expression.
- **Panel secrets stay where they are.** PasarGuard's `.env` and Rebecca's
database URL are read only for the keys the installer needs, never printed,
and never copied into a backup. A MySQL/MariaDB password is never asked for
or read.
- **Backups record their panel** and are never restored onto another one.

### Changed

- `row-template version` shows the panel it serves; on 3X-UI it still shows the
minimum-supported and detected versions.
- `row-template uninstall` returns each panel to the page it had before
Row-Template, and leaves a page you chose afterwards alone.
- The `on_hold` state on PasarGuard and Rebecca is shown as active: with its
"starts on first connection" duration on PasarGuard, and with an unknown
expiry on Rebecca, which does not give the page that duration
(`docs/design/PANEL-ON-HOLD-DECISION.md`).

### Known limitations

- On PasarGuard and Rebecca the page shows the values as of when it was opened;
live refresh (`?format=info`) is 3X-UI only, because both panels serve live
status on a path suffix.
- PasarGuard's page title (`subTitle`) and Clash templates are not produced.
- Rebecca on MySQL/MariaDB needs its one setting entered in the dashboard.
- Rebecca's Docker image (`rebeccapanel/rebecca` on Docker Hub) is still the
0.0.x Python edition, which cannot render this page. The installer
identifies it and refuses before changing anything; Rebecca's own
`rebecca migrate-binary` moves a Docker install to 1.x.

### Documentation

- The compatibility page, installation, configuration and troubleshooting
cover all three panels, in English, Persian and Arabic; the READMEs in all
five languages describe PasarGuard and Rebecca as supported.
- `docs/design/PASARGUARD-INSTALLER-AUDIT.md` and
`docs/design/REBECCA-INSTALLER-AUDIT.md` record, from each panel's source,
what activation is and how the installer follows it.

### Development

- The test suite renders the PasarGuard and Rebecca pages with the real
engines, and needs Python 3 with Jinja2 as well as Go; a missing engine is a
failure, never a skip.
- `tools/make-release.sh` writes checksums in the text form on every platform.

### Upgrading

- From **1.2.0** or **1.1.0** on 3X-UI: run `row-template update`. From 1.1.0,
the next `row-template`, `row-template config` or `row-template verify`
completes the install. Your design, branding and panel wiring are kept.
- On **PasarGuard** or **Rebecca**: run the installer. Earlier releases did not
install on these panels. Rebecca must be 1.x (its binary install); a Docker
Rebecca is 0.0.x and is refused until it is moved to 1.x.
- **Rolling back after the update.** `row-template update` backs up the version
it replaces, and `row-template rollback --to <that backup>` returns to its page
and branding. A rollback restores the page and the recorded version, not the
manager itself: `row-template` stays 1.3.0 and reports the version it rolled
back to, and the next `row-template update` returns to 1.3.0. Only the two
newest backups are kept, so the pre-update backup is replaced after two
further changes (a design switch, an update or a rollback each make one).

## [1.2.1] - Unreleased (shipped in 1.3.0)

Fixes the update from 1.1.0, which could leave the manager with no designs to
choose from. 3X-UI (>= 3.6.0) stays the only supported panel.

### Fixed

- **One `row-template update` is enough to move from 1.1.0.** 1.1.0's own
updater installs the new version but copies only four files, so in 1.2.0 the
designs were missing until a second update, and **Reconfigure branding →
Template** said "No templates are installed". Now the first time you open
`row-template`, or run `row-template config` or `row-template verify` as
root, after the update, it downloads the rest of the same release — every
design and the remaining installer files, checksum-verified — before doing
anything else. It downloads the version you have installed, never a newer
one, and changes nothing else: the live page, branding, selected design and
backups stay as they are. If the release cannot be reached, it says so and
tries again the next time the manager opens.
- **Designs found outside their folder are moved back.** The designs belong in
`dist/templates/`. A copy at the install root's `templates/` — where a copied
or extracted release leaves it — is now moved into place automatically by
`install`, `update` and `verify`. Each design is checked against its own
checksum first; one that fails is reported and left where it is, and files
Row-Template does not recognise are never removed.
- **Changing branding works on an install the 1.1.0 updater left incomplete.**
`row-template config` and the manager's branding editors refused with "the
template selection could not be reconciled" until a second update; they now
complete the install first.
- **`row-template verify` names missing and damaged designs.** A design that
fails its checksum is reported by name as a failure; missing designs are a
warning that names them. It previously reported a failing store without
saying which design, and did not report missing ones at all.

### Changed

- `row-template verify` is no longer strictly read-only. Run as root, it first
repairs the template store — moving misplaced designs back into place and
downloading any the installed version is missing, from that same release —
and then checks it. It makes no other change, and none at all when run
without root.

### Documentation

- The compatibility page lists, per panel, what the installer can do today:
detection, install, activation, verification, and backup and rollback. For
PasarGuard and Rebecca the answer is none of them — only the page shells are
built and packaged — so both stay **research targets, not supported panels**.
A test checks every README and compatibility page against the installer.

### Known issues

- Rolling back from 1.2.x to a backup taken under 1.1.0 fails with "backup
artifact matches no installed template": 1.1.0's page is not one of the
current release's designs. The rollback stops before changing anything, so
the running page stays as it was. Rolling back to a backup taken under 1.2.x
is not affected.

### Upgrading

- From **1.1.0**: run `row-template update`. The next `row-template`,
`row-template config` or `row-template verify` completes the install.
- From **1.2.0**: run `row-template update`. This also completes a 1.2.0
install that the 1.1.0 updater left without its designs.

## [1.2.0] - 2026-09-24

Turns Row-Template from one page into a collection of designs. A minor release:
Row stays the default design, and 3X-UI (>= 3.6.0) stays the only supported
Expand Down Expand Up @@ -84,7 +317,8 @@ panel.
page updates and your branding is kept — but copies only the library and
the command, so only Row is available. The second, carried out by 1.2.0,
installs every design and the remaining installer files. `row-template
verify` reports whether the second run is still needed.
verify` reports whether the second run is still needed. (Fixed in 1.2.1,
which needs one run.)

## [1.1.0] - 2026-08-30

Expand Down Expand Up @@ -162,6 +396,8 @@ First stable release.
- Requires 3X-UI (MHSanaei) **>= 3.6.0**; validated against stock 3.7.0.
- Recommended operating system: Ubuntu 24.04 LTS (x86_64).

[1.2.0]: https://github.com/iitzSeriZdev/Row-Template/compare/v1.1.0...main
[1.3.0]: https://github.com/iitzSeriZdev/Row-Template/releases/tag/v1.3.0
[1.2.1]: https://github.com/iitzSeriZdev/Row-Template/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/iitzSeriZdev/Row-Template/releases/tag/v1.2.0
[1.1.0]: https://github.com/iitzSeriZdev/Row-Template/releases/tag/v1.1.0
[1.0.0]: https://github.com/iitzSeriZdev/Row-Template/releases/tag/v1.0.0
17 changes: 13 additions & 4 deletions PROVENANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,29 @@ Every release published on GitHub carries these assets:
| ----- | ------- |
| `row-template-<version>.tar.gz` | The runtime payload — see below. |
| `SHA256SUMS` | The SHA-256 checksum of the tarball above. |
| `manifest.txt` | Plain-text metadata (`name`, `version`, `artifact`, `min_xui`, `created`), parsed as data — never executed. |
| `manifest.txt` | Plain-text metadata (`name`, `version`, `artifact`, `min_xui`, `created`), parsed as data — never executed. `min_xui` applies to 3X-UI only. |
| `install.sh` | The bootstrap used by the one-command installer. |

The tarball expands to a single `row-template-<version>/` directory:

| Path | Contents |
| ---- | -------- |
| `template.html` | The Row design, the page an older installed version updates against. |
| `templates/<id>/template.html` (+ `.sha256`) | Every selectable design, each with its own checksum. |
| `shells/<panel>/<id>/shell.html` (+ `.sha256`) | Each design's page shell per panel, packaged for research; the installer does not place them. |
| `templates/<id>/template.html` (+ `.sha256`) | Every selectable design for 3X-UI, each with its own checksum. |
| `shells/<panel>/<id>/shell.html` (+ `.sha256`) | Every design for every panel, each with its own checksum. On PasarGuard (Jinja2) and Rebecca 1.x (pongo2) the installer places the one you select, and refuses a page built for another panel or by a release before 1.3.0. `shells/3xui/` is byte-identical to `templates/`, which is what 3X-UI installs use. |
| `VERSION`, `install.sh`, `lib/`, `bin/` | The version, the installer and the `row-template` manager. |
| `panels/` | The panel interface layer the manager loads; installed next to `lib/`. |
| `panels/` | The panel interface and one adapter per panel (`3xui.sh`, `pasarguard.sh`, `rebecca.sh`); installed next to `lib/`. |
| `SHA256SUMS` | The checksum of every payload file, so the contents can be checked after extraction as well. |

Every design is built from this repository's own sources (`src/`). Meter and
Notebook (1.3.0) were contributed by the project's author and ported onto the
shared runtime; like every other design they contain no third-party code beyond
the bundled QR generator and font listed in the README's License section. The
PasarGuard and Rebecca pages contain no code from either panel: both panels are
AGPL-3.0, so the preludes and the test harnesses that render them with the
panels' real engines are independent implementations, written from the source
audits in `docs/design/`.

The build is deterministic: the same sources always produce a byte-identical
`row-template-<version>.tar.gz`. Anyone can rebuild it from a checkout with
`tools/make-release.sh` (which needs Node.js to build the designs) and compare
Expand Down
Loading
Loading