Skip to content

Developer Guide

Alexander Phillips edited this page Sep 20, 2026 · 1 revision

Developer Guide

Architecture

Installed source lives under source/appdata.cleanup.plus/usr/local/emhttp/plugins/appdata.cleanup.plus/.

File/component Responsibility
AppdataCleanupPlus.page Unraid page, translated strings and browser bootstrap
include/exec.php POST dispatch, origin/CSRF boundary and locking
include/api.php UI actions and response/diagnostic builders
include/helpers.php Settings, atomic persistence, snapshots, metrics and locks
include/dashboard.php Discovery, candidate construction and statistics
include/pathUtils.php Canonical path and ownership/security boundaries
include/quarantine.php Move, restore, purge, schedule and marker recovery
include/zfs.php Exact dataset resolution and destruction validation
include/templates.php Template ownership, archive and restore
include/fixtures.php Managed test fixtures
include/i18n.php, locales/ Server translation and bundled catalogs/plurals
scripts/appdata.cleanup.plus.js Browser state, requests and workflows
Shared/panels JavaScript Escaping, formatting, common behavior and panel HTML
styles/appdata.cleanup.plus.css Scoped native-theme-compatible styling

The repository root pkg_build.sh is authoritative; the source-tree builder is a forwarding wrapper. plugins/appdata.cleanup.plus.plg, archive/ and appdata.cleanup.plus.xml are package/installation surfaces.

Request lifecycle and internal actions

The browser receives IDs tied to a server scan, submits an action with session/CSRF context, and the dispatcher validates the request and acquires required locks. Handlers resolve trusted state, revalidate current conditions, mutate only when authorized, persist/audit and return presentation-localized responses.

Internal actions include:

Area Actions
Scan/details getOrphanAppdata, hydrateCandidateStats, getCandidateDetails
Settings/sources saveSafetySettings, browseAppdataSourcePath, updateCandidateState
Cleanup/progress executeCandidateAction, getOperationProgress
Quarantine getQuarantineSummary, getQuarantineEntries, inspectQuarantineRestore, quarantineManagerAction, updateQuarantinePurgeSchedule
Maintenance/support templateManagerAction, fixtureManagerAction, getAuditHistory, getDiagnosticsBundle

This is not a versioned public automation API. Do not document arbitrary-path requests or bypass server-issued IDs.

Validation

CI configuration is the current authoritative sequence. Relevant checks include:

node scripts/build_i18n.mjs --check
php tests/i18n_smoke.php
node tests/i18n_client.js
node tests/i18n_page.js
node tests/i18n_flows.js
php tests/php_function_checker.php
php scripts/check_php_functions.php
php tests/ownership_templates.php
bash scripts/test_ui_confirmation.sh
bash scripts/test_diagnostics_privacy.sh
bash scripts/test_behavior.sh
bash scripts/release_guard.sh
bash scripts/ca_readiness_guard.sh
bash scripts/test_ca_canonical_urls.sh

Also run PHP lint, all shipped JavaScript syntax checks, client security tests, shell syntax/ShellCheck and package parity/line-ending guards as applicable. CI runs browser fixture, theme and maintenance suites with pinned Playwright/jQuery test dependencies. ACP_BROWSER_MODULES points at that tooling's node_modules, not a shipped runtime dependency.

Use isolated fixtures only. Passing synthetic filesystem/ZFS tests does not establish successful live dataset destruction. Native-theme fixtures do not certify every browser. See validation notes, while checking version-sensitive statements against current source.

Localization changes

Use complete sentence templates and named placeholders. Keep persistent machine fields literal and translate only allowlisted presentation fields after actions finish. Escape translated and user-provided values for their output context.

Maintain the English master, message/plural definitions and overrides. The offline catalog check must pass. node scripts/build_i18n.mjs --translate is a maintainer operation that sends public source phrases to Google Translate; it is not part of runtime or offline validation.

See localization reference for CLDR rules, aliases and override files. Test plural behavior and actual UI flows; do not claim native-speaker review from passing tests.

Packaging and release

Work on dev. For shipped changes, run focused/full relevant validation, then:

bash pkg_build.sh --branch dev --dry-run
# Supply real user-facing notes through APPDATA_CLEANUP_PLUS_CHANGE_NOTES.
bash pkg_build.sh --branch dev
bash scripts/release_guard.sh
bash scripts/ca_readiness_guard.sh

Use the builder's resolved version and checksum; do not manufacture either. Verify manifest, archive contents/MD5, canonical URLs, CA metadata and changelog agreement. Preserve package history.

Stable promotion uses scripts/release_main.sh --dry-run followed by the authorized scripts/release_main.sh workflow. It manages main packaging, release/tag publication, verification and back-sync. Never substitute a manual URL identity change.

Documentation-only wiki edits do not require a plugin package. For code changes, inspect the full diff, keep secrets/private diagnostics out of commits, push the intended branch and monitor applicable CI.

Security and privacy contracts

Preserve locks, session snapshots, origin/CSRF checks, path canonicalization, stopped-container/Compose protection, no-follow deletion, collision-free restore and exact ZFS descendant validation.

New diagnostic fields require allowlists, key/value scrubbing, bounded collection and privacy regression coverage. Read-only endpoints must not sweep or delete data. Keep logs and fixtures free of private machine information.

Clone this wiki locally