privacy-plugin
Specialized tool for managing J2Commerce privacy data, consent, and GDPR/DSGVO compliance tasks.
Install
mkdir -p .claude/skills/privacy-plugin && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/17403" && unzip -o skill.zip -d .claude/skills/privacy-plugin && rm skill.zipInstalls to .claude/skills/privacy-plugin
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Deep knowledge of the plg_privacy_j2commerce plugin. Use when working on GDPR/DSGVO compliance, retention logic, lifetime license detection, template integration, checkout consent, or data export/deletion.Key capabilities
- →Export J2Commerce orders, addresses, and cart data
- →Enforce configurable retention periods for data deletion
- →Anonymize orders outside the retention period
- →Detect lifetime licenses to preserve email after retention expires
- →Add a consent checkbox to the J2Commerce checkout
- →Run a scheduled automatic cleanup task
How it works
The plugin extends Joomla's `com_privacy` to handle J2Commerce-specific data, including exporting, enforcing retention, anonymizing orders, detecting lifetime licenses, adding checkout consent, and running cleanup tasks.
Inputs & outputs
When to use privacy-plugin
- →Configure data retention policies
- →Anonymize expired orders
- →Integrate privacy consent at checkout
- →Generate data export reports
About this skill
Privacy Plugin — Domain Knowledge
Location
j2commerce/plg_privacy_j2commerce/
What This Plugin Does
Extends Joomla's com_privacy with J2Commerce-specific data handling:
- Exports J2Commerce orders and addresses, optional Joomla user/profile/action-log data, and AcyMailing subscriber data on privacy export requests
- Carries out removal requests: deletes addresses, the carts of the account and AcyMailing data, anonymizes orders outside the retention period, keeps orders within it and reports them (administrator message, customer e-mail)
- Anonymizes orders outside the retention period instead of deleting them (registered users and, via the task, guest orders)
- Detects lifetime licenses: those orders keep only their order e-mail after the retention period (provisional, see Decisions)
- Adds a consent checkbox to the J2Commerce checkout; on J2Commerce 6 validates it server-side and records one
#__privacy_consentsrow per order (bundled system plugin) - Renders a self-service privacy tab in the J2Commerce MyProfile page (consent status, request buttons per option:
com_privacyform for logged-in users,mailto:for guests) - Runs a scheduled automatic cleanup task
Key Files
| File | Purpose |
|---|---|
src/Extension/J2Commerce.php | Main plugin class — all event handlers |
plugins/task/j2commerceprivacy/src/Extension/J2CommercePrivacy.php | Scheduled cleanup task (separate task plugin) |
plugins/system/j2commerceprivacy/src/Extension/J2CommercePrivacy.php | onMailBeforeRendering: links the com_privacy administrator request mail to the confirmation page; checkout consent on J2Commerce 6 (onAfterRoute, onJ2CommerceAfterDisplayShippingPayment, onJ2CommerceCheckoutCleanup; records the consent on checkout.confirmPayment); bundled system plugin installed by script.php |
src/Consent/ConsentRepository.php | #__privacy_consents: one record per order without duplicates, status lookup by user_id or, for guests, only the order of the session token + e-mail |
layouts/privacy_tab.php | Privacy tab markup, rendered by the myprofile/default_privacy.php overrides |
src/Frontend/PrivacyOptions.php | Frontend options for the MyProfile overrides (show_privacy_section, show_delete_address, show_export_data, show_delete_all), all off while the plugin is disabled; loads the plugin language |
script.php | Install/update/uninstall, post-install message |
language/en-GB/plg_privacy_j2commerce.ini | All translatable strings |
Events Handled
| Event | Purpose |
|---|---|
onPrivacyExportRequest | Collect J2Commerce data for export |
onPrivacyCanRemoveData | Does not block for retention reasons (orders within the retention period are kept and reported; lifetime-license orders keep only their e-mail, provisional); only exception: Joomla found an account of a different address (muller@ for müller@), see the e-mail comparison decision |
onPrivacyRemoveData | Anonymize/delete data |
onAjaxJ2commercePrivacy | Address deletion (task=deleteAddress, logged-in, JSON) and the confirmation page for privacy requests without login (task=confirmRequest, HTML); results go through $event->addResult(). The form token is checked by the plugin itself (hasValidToken(): X-CSRF-Token header, POST field or query parameter, as AJAX Forms), never with Session::checkToken(): for a request without session cookie that redirects with 303 to Route::_('index.php'), the router merges the com_ajax query into it with &, and every hop loops (dev check 13.10.2026). Plugin classes call Route::_() with xhtml=false; 04b checks both statically |
See references/architecture.md for full details.
Decisions (maintainer, PR #187)
| Topic | Decision |
|---|---|
| Compatibility | Joomla 5.4 or later (5.4.x, 6.x), PHP 8.1+; no compatibility layer for Joomla 5.0 to 5.3. No dispatcher in plugin constructors or setDispatcher() in service providers (Joomla sets it on load) |
| Guest access | One order token = exactly one order (native J2Commerce logic): the Privacy tab of a guest session shows only the order of guest_order_token + guest_order_email, never other orders of the same address |
| Checkout checkbox | J2Commerce 6: rendered by the system plugin through the core event AfterDisplayShippingPayment (J2Commerce 6.3.4 or later, installer warns for older versions); no J2Commerce 6 checkout override is shipped. Required only through the plugin options "Show Consent Checkbox" and "Consent Required". No cart (ID 0): not stored, a required consent is refused. Recorded only after J2Commerce accepted the order (capturePlacement() on checkout.confirmPayment with form token or gateway return GET, recordAcceptedOrderConsent() at shutdown: order exists, same cart, order_state_id != 5), once per order (removeDuplicateConsents()) |
| IP address and user agent | Stored in the consent record as proof of consent and for shop security (legitimate interest; IP via IpHelper::getIp()). Removed when the order is anonymized, and by the task when the record is outside the retention period (10 years by default, from the end of the fiscal year in the site time zone) or its order was deleted or already anonymized (removeStaleEvidence()); the record stays as evidence without personal data |
| Retention period | Counted from the end of the fiscal year of the order (fiscal_year_end, default 12-31, OR Art. 958f) in the site time zone; the SQL cutoff is converted to UTC |
| Removal requests | Not refused (only exception: Joomla found an account of a different address (muller@ for müller@), see the e-mail comparison decision): everything not subject to a retention obligation is removed; orders within the retention period are kept and reported to the administrator and, by e-mail in the customer's language, to the customer |
| Lifetime licenses | Variant A, provisional (confirmation pending): a removal request is carried out; after the retention period only the order e-mail of lifetime-license orders is kept (license reactivation); the same rule per order in the removal request and the task, fail-closed |
| Action log | Joomla's action log (#__action_logs, e.g. login records) is separate: the plugin only exports it (include_joomla_data) and, with activity_logging, adds its own entries (with IP address); it never changes or deletes existing entries |
| Operators | Must define the storage period of consent records and describe the stored data (IP address, user agent, order number, time), its purpose and storage period in their privacy policy; consent records without personal data are not deleted automatically |
| J2Commerce stack | Support\J2CommerceStack: the active shop (display, recording consent) is decided by the enabled component, the same rule as in all Advans J2Commerce extensions: com_j2commerce enabled with its tables → #__j2commerce_*; otherwise com_j2store enabled with its tables → #__j2store_*; an enabled component without tables is skipped, an installed but disabled one does not count; otherwise the J2Commerce 6 tables if they exist. Removal, anonymization, retention cleanup and export run on all existing sets (dataSets(), forEachDataSet() / task dataSetOverride), so migration copies in #__j2store_* are cleaned too |
| Legacy consents | Records of the earlier advans template override (PLG_PRIVACY_J2COMMERCE, e-mail in the body, partly created afterwards) are never assigned to an order: only anonymized (anonymizeLegacyConsents(): installation and update for all accounts with an admin message, removal request scoped to the user plus guest records with the request/account e-mail, task; batches), subject PLG_SYSTEM_J2COMMERCEPRIVACY_CONSENT_SUBJECT_LEGACY, neutral body in the website's default site language (com_languages → site, fallback the packaged en-GB file, and if even that is missing the key itself is stored and the next unscoped run replaces it with the text) and state = -1 (invalid, hidden from the com_privacy lists), not shown or counted in the Privacy tab. The unscoped path also repairs bodies that an older version stored as the raw language key; a scoped removal request never touches another account's record |
| Guest requests (owner decision 2026-10-12) | Export, retention check, anonymization, guest addresses and the guest consent export match the account (user_id) and guest records (user_id = 0) with the request or account e-mail (ownerCondition(), trimmed, case-insensitive, never another account, never [email protected]); user = null is processed by the request e-mail; guest carts are never touched. Guests confirm an administrator-created request on task=confirmRequest (e-mail + code, checks as com_privacy ConfirmModel, status 0 -> 1, super users + action log, expired matching code -> -1, failures limited in 15 min: 5 per session, 5 per address and 20 per client IP in the table #__privacy_j2commerce_attempts (Security\ConfirmAttempts, HMAC hashes with the site secret only, purged on write and by the task, created by manifest SQL plus a postflight backstop), uniform answer and work while blocked); the system plugin points {TOKENURL}/{FORMURL} of com_privacy.notification.admin.* there (relies on MailTemplate replacing tokenurl before token). Option guest_confirmation (default on) |
| E-mail comparison (finding 13.10.2026) | Exact after ConsentRepository::normaliseAddress() (trim, Unicode lower case): SQL only preselects (addressPrefilter(): ASCII values by ASCII lower case under utf8mb4_bin / PostgreSQL "C", every value with non-ASCII characters as a candidate, so no database case table or locale loses a match; addressValues() reads in batches of BATCH_SIZE), PHP decides (addressValues(), normaliseAddress()), rows are then addressed by the exact stored value (exactValuesCondition(): `utf8mb |
Content truncated.
When not to use it
- →When working with general Joomla privacy features not specific to J2Commerce
- →When the goal is to delete data immediately without retention period enforcement
- →When the plugin's specific event handlers are not relevant
Limitations
- →The plugin is specific to `plg_privacy_j2commerce`
- →The plugin anonymizes orders instead of deleting them outside the retention period
- →The plugin requires specific event handlers like `onPrivacyExportRequest` and `onPrivacyRemoveData`
How it compares
This plugin provides specialized privacy functionalities tailored for J2Commerce data, such as anonymizing orders and detecting lifetime licenses, which are not typically covered by generic privacy plugins.
Compared to similar skills
privacy-plugin side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| privacy-plugin (this skill) | 0 | 3mo | No flags | Intermediate |
| command-injection-testing | 1 | 9mo | Review | Advanced |
| file-upload-testing | 1 | 9mo | Review | Advanced |
| security-hardening | 0 | 4mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
command-injection-testing
Ed1s0nZ
命令注入漏洞测试的专业技能和方法论
file-upload-testing
Ed1s0nZ
文件上传漏洞测试的专业技能和方法论
security-hardening
boctulus
Security best practices for SimpleRest including JWT configuration, ACL hardening, input sanitization, CSRF protection, and encryption.
orbit-sec-supply-chain
adityaarsharma
Supply-chain security audit — Composer + npm dependency CVE check, license compatibility (GPL-compatible only), abandoned package detection, typosquatting risk, lockfile integrity, post-install / preinstall scripts that smell like supply-chain attacks. Use when the user says "supply chain audit", "d
api-security-best-practices
davila7
Implement secure API design patterns including authentication, authorization, input validation, rate limiting, and protection against common API vulnerabilities
laravel-specialist
Jeffallan
Use when building Laravel 10+ applications requiring Eloquent ORM, API resources, or queue systems. Invoke for Laravel models, Livewire components, Sanctum authentication, Horizon queues.