@emplugins/emprivacy 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -0
- package/README.md +145 -0
- package/dist/config-BJ1LHuri.mjs +166 -0
- package/dist/config-CqOtRoQR.d.mts +63 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.mjs +29 -0
- package/dist/sandbox-entry.d.mts +283 -0
- package/dist/sandbox-entry.mjs +693 -0
- package/docs/DEVELOPMENT.md +36 -0
- package/docs/GETTING_STARTED.md +140 -0
- package/docs/PLUGIN_SETTINGS.md +181 -0
- package/docs/RELEASES.md +81 -0
- package/docs/RELEASE_NOTES.md +109 -0
- package/docs/TESTING.md +53 -0
- package/package.json +88 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# Development — dependencies and security
|
|
4
|
+
|
|
5
|
+
## What EmPrivacy ships to npm
|
|
6
|
+
|
|
7
|
+
Runtime dependencies for the published package are **`zod`** only. **EmDash** is a **peer dependency** (your site installs it). The **`emdash`** package in this repo’s `devDependencies` exists so local `typecheck` and tests can resolve `import … from "emdash"`.
|
|
8
|
+
|
|
9
|
+
## Package manager
|
|
10
|
+
|
|
11
|
+
This repo uses **pnpm** (`packageManager` in `package.json`). Install and CI:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm install
|
|
15
|
+
pnpm run typecheck
|
|
16
|
+
pnpm test
|
|
17
|
+
pnpm run build
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## `pnpm audit` and the Kysely override
|
|
21
|
+
|
|
22
|
+
The `emdash` dev dependency pulls in a SQL stack that historically resolved **`kysely@0.27.x`**, which is affected by advisories (for example [GHSA-wmrf-hv6w-mr66](https://github.com/advisories/GHSA-wmrf-hv6w-mr66) and [GHSA-8cpq-38p9-67gx](https://github.com/advisories/GHSA-8cpq-38p9-67gx)) until patched releases.
|
|
23
|
+
|
|
24
|
+
**This repository pins a safe Kysely** via `pnpm.overrides` in `package.json` (currently `0.29.2`, above the patched range for known advisories). Regenerate the lockfile with `pnpm install` after changing overrides.
|
|
25
|
+
|
|
26
|
+
- Full dev tree: `pnpm audit` should report **0 vulnerabilities** after a clean `pnpm install --frozen-lockfile`. If upstream `emdash` introduces new transitive advisories, track them here and adjust `pnpm.overrides` when a patched release exists.
|
|
27
|
+
- Production install only: `pnpm audit --omit=dev` reflects **only** published runtime deps (currently `zod`).
|
|
28
|
+
|
|
29
|
+
## Deprecation warnings you may still see
|
|
30
|
+
|
|
31
|
+
`pnpm install` can still print **deprecated** messages for **transitive** packages **not** maintained by this repo, for example:
|
|
32
|
+
|
|
33
|
+
- **`prebuild-install`** — pulled in by `better-sqlite3` (used by `emdash`). The [package is deprecated](https://www.npmjs.com/package/prebuild-install) pending upstream changes in native addons.
|
|
34
|
+
- **`node-domexception`** — used under the [libsql / fetch](https://www.npmjs.com/package/node-domexception) client stack; the package is deprecated in favor of native `DOMException` in newer Node.
|
|
35
|
+
|
|
36
|
+
Those warnings do not imply that EmPrivacy’s own source is outdated; they track **upstream** `emdash` and its dependencies. Re-run `pnpm audit` to confirm there are no known vulnerabilities for your install.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# Getting started with EmPrivacy
|
|
4
|
+
|
|
5
|
+
This guide is for site builders who want cookie consent working on an **EmDash** site without reading plugin source.
|
|
6
|
+
|
|
7
|
+
## What you get
|
|
8
|
+
|
|
9
|
+
- A **banner** on first visit (or after you change **Policy / consent version**).
|
|
10
|
+
- Toggles for **Analytics** and **Marketing** (essential/theme cookies are not blocked by this plugin—see the main README).
|
|
11
|
+
- **Privacy and cookie policy links** you control: usually an EmDash **Page** via a short **path** (e.g. `/privacy`) or a full `https://` link. Paths are turned into full URLs using EmDash’s URL helper so they work in dev and production.
|
|
12
|
+
- **Analytics** — choose a **platform** in admin (e.g. **Cloudflare Web Analytics** and your **site token**, or **Custom** with one `https://` script URL per line, or **None**). **Marketing** — `https` script URLs, one per line. Scripts load **after** consent for that category.
|
|
13
|
+
|
|
14
|
+
## Before you begin
|
|
15
|
+
|
|
16
|
+
1. An EmDash site with `emdash` in `astro.config` ([plugins overview](https://docs.emdashcms.com/plugins/overview/)).
|
|
17
|
+
2. Ability to edit **`astro.config`** and redeploy (or run locally).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Step 1 — Install the package
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @emplugins/emprivacy
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The package is versioned with **semver** on npm; to pin a line, use a range such as `@emplugins/emprivacy@^1.0.0`. See [RELEASES.md](./RELEASES.md) for how releases are numbered.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Step 2 — Add the plugin to Astro
|
|
32
|
+
|
|
33
|
+
Open `astro.config.mjs` (or `.ts`).
|
|
34
|
+
|
|
35
|
+
1. Import the plugin:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { emprivacyPlugin } from "@emplugins/emprivacy";
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
2. Add **`emprivacyPlugin()`** to **`emdash({ plugins: [...] })`**. Put **EmPrivacy first** if you use other plugins that inject scripts or metadata.
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
emdash({
|
|
45
|
+
plugins: [
|
|
46
|
+
emprivacyPlugin(),
|
|
47
|
+
// ...other plugins
|
|
48
|
+
],
|
|
49
|
+
}),
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
3. Save and restart the dev server (or rebuild).
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Step 3 — Layout must include EmDash hooks
|
|
57
|
+
|
|
58
|
+
Your base layout must include EmDash’s head/body injection points (e.g. `<EmDashHead />`, `<EmDashBodyStart />`, `<EmDashBodyEnd />` or your theme’s equivalents). Otherwise the banner may not render. See [EmDash docs](https://docs.emdashcms.com/).
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Step 4 — Create or pick your Privacy Policy Page (EmDash)
|
|
63
|
+
|
|
64
|
+
If you already have a **Page** for your privacy policy:
|
|
65
|
+
|
|
66
|
+
1. Open that Page on the **public site** (or preview) and look at the **path** in the address bar — for example `https://yoursite.com/privacy` → use **`/privacy`**.
|
|
67
|
+
2. In **EmPrivacy** settings, paste that path into **Privacy policy — EmDash Page path or https URL** (or paste a full `https://…` URL if the policy is not an EmDash Page).
|
|
68
|
+
|
|
69
|
+
If you still need a Page: create and publish a Page in EmDash, note its URL path, then enter that path in EmPrivacy as above.
|
|
70
|
+
|
|
71
|
+
Same idea for an optional **Cookie policy** field: path (e.g. `/cookies`) or `https://…`.
|
|
72
|
+
|
|
73
|
+
**Not accepted:** bare domains (`example.com`), `http://…` URLs, or protocol-relative links (`//…`). Use **`/your-path`** or **`https://…`**.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Step 5 — Configure EmPrivacy in the admin
|
|
78
|
+
|
|
79
|
+
1. Log into the **site admin**.
|
|
80
|
+
2. Open **EmPrivacy** (shield icon).
|
|
81
|
+
3. Set:
|
|
82
|
+
- **Privacy policy** — path or `https` (see Step 4).
|
|
83
|
+
- **Cookie policy** — optional; same rules.
|
|
84
|
+
- **Banner title** and **Short notice**.
|
|
85
|
+
- **Policy / consent version** — bump when you change legal text so visitors see the banner again.
|
|
86
|
+
- **Analytics platform** — *Cloudflare Web Analytics* (default), *None*, or *Custom* (see below).
|
|
87
|
+
- **Cloudflare** — In the [Cloudflare dashboard](https://dash.cloudflare.com/) → **Web Analytics**, copy the **site token** for your property and paste it into **Cloudflare Web Analytics site token**. EmPrivacy injects the standard `beacon.min.js` script with `data-cf-beacon='{"token":"…"}'` after the visitor consents to analytics.
|
|
88
|
+
- **Custom analytics** — If you pick **Custom**, one **`https://`** script URL per line, `src` only (not a full `<script>` block); see [Custom script URLs (not HTML)](#custom-script-urls-not-html) below.
|
|
89
|
+
- **Marketing script URLs** — one **`https://`** URL per line, or leave blank.
|
|
90
|
+
4. Optional: **Strict defaults**, **Google Consent Mode v2**, **Log consent to server** (see main README).
|
|
91
|
+
5. **Save settings**.
|
|
92
|
+
|
|
93
|
+
**Custom script URLs (not HTML)** (only when **Analytics** is set to **Custom**)
|
|
94
|
+
|
|
95
|
+
Each line must be a **full https URL** to a `.js` file (the script `src`). **Do not** paste HTML comments, tags, or attributes. EmPrivacy injects with `<script src="…">` only (no `data-*` for custom mode).
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Step 6 — Verify on the public site
|
|
100
|
+
|
|
101
|
+
1. Use a **private/incognito** window (or clear site cookies).
|
|
102
|
+
2. Confirm the **banner** appears. After you save a choice, a small **cookie button** stays in the bottom-left; click it to **change** analytics/marketing choices (the page reloads when you save from that panel so consent stays in sync with loaded scripts).
|
|
103
|
+
3. Click **Privacy policy** (and **Cookie policy** if set): they should open the EmDash Page or external URL you configured.
|
|
104
|
+
4. In **Developer tools → Network**: before accepting, listed third-party scripts should not load; after consent, they should load only for the categories you allowed.
|
|
105
|
+
5. Reload: the banner should stay dismissed if the cookie matches your **Policy / consent version**.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Step 7 — Testing before go-live
|
|
110
|
+
|
|
111
|
+
Run automated checks if you develop the plugin or CI:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm run typecheck && npm run build && npm test
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
For a full staging checklist (banner, strict mode, admin, optional logging, Google), see **[TESTING.md](./TESTING.md)**.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Common problems
|
|
122
|
+
|
|
123
|
+
| Problem | What to check |
|
|
124
|
+
|--------|----------------|
|
|
125
|
+
| Nothing appears | EmDash layout missing head/body components; plugin not in `plugins: []`; dev server restarted after config change |
|
|
126
|
+
| Scripts load before consent | No hard-coded third-party scripts in the theme; EmPrivacy listed **before** those plugins in `plugins` |
|
|
127
|
+
| EmPrivacy missing in admin | Plugin not installed or `astro.config` wrong; check build errors |
|
|
128
|
+
| Save fails on privacy/cookie | Value must be a **root-relative path** (`/something`) or **`https://…`** (not `http://` or a bare hostname) |
|
|
129
|
+
| Save fails: “Invalid … script URL” | For **Custom** analytics or **Marketing** URLs, enter one **https URL** per line (the script `src`), not a `<script>` tag. See [Custom script URLs (not HTML)](#custom-script-urls-not-html) |
|
|
130
|
+
| Privacy link 404 or wrong page | Path must match the live EmDash route (compare with the address bar when viewing that Page) |
|
|
131
|
+
| Link works on staging but path looks wrong | Paths are resolved with EmDash `ctx.url()`; ensure the Page is published and the path matches production routing |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## More reading
|
|
136
|
+
|
|
137
|
+
- Main **[README](../README.md)** — disclaimer, features table, registration order, full testing section
|
|
138
|
+
- **[TESTING.md](./TESTING.md)** — pre-deploy QA and CI
|
|
139
|
+
- **[PLUGIN_SETTINGS.md](./PLUGIN_SETTINGS.md)** — what each admin setting does (with examples)
|
|
140
|
+
- **[CONTRIBUTING.md](../CONTRIBUTING.md)** — how to contribute
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# EmPrivacy — Plugin settings reference
|
|
4
|
+
|
|
5
|
+
This page documents every field on the **EmPrivacy** admin settings page (shield icon → **EmPrivacy**).
|
|
6
|
+
|
|
7
|
+
It’s written for site owners and maintainers who want to understand:
|
|
8
|
+
|
|
9
|
+
- What each setting **does**
|
|
10
|
+
- What input format is expected (with **examples**)
|
|
11
|
+
- What public-site behavior changes when you change it
|
|
12
|
+
|
|
13
|
+
> Note: EmPrivacy is a technical implementation tool, not legal advice. You are responsible for configuring categories and scripts consistently with your privacy/cookie policies and applicable laws.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Banner settings
|
|
18
|
+
|
|
19
|
+
### Banner title
|
|
20
|
+
|
|
21
|
+
- **What it is**: The heading shown at the top of the cookie banner and the reopen panel.
|
|
22
|
+
- **Example**: `Cookies & privacy`
|
|
23
|
+
- **Behavior**: Updates visible banner UI copy only (no effect on consent logic).
|
|
24
|
+
|
|
25
|
+
### Short notice
|
|
26
|
+
|
|
27
|
+
- **What it is**: The banner message text shown under the title.
|
|
28
|
+
- **Example**: `We use cookies to run this site and optionally for analytics and marketing. You can accept or customize your choices.`
|
|
29
|
+
- **Behavior**: Updates visible banner UI copy only (no effect on consent logic).
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Policy links (shown in the banner)
|
|
34
|
+
|
|
35
|
+
These links are rendered as “Privacy policy” (and optionally “Cookie policy”) in the banner and reopen panel.
|
|
36
|
+
|
|
37
|
+
### Privacy policy — EmDash Page path or https URL
|
|
38
|
+
|
|
39
|
+
- **What it is**: Where your privacy policy lives.
|
|
40
|
+
- **Allowed inputs**:
|
|
41
|
+
- A **root-relative path** to an EmDash Page (resolved to a full URL by EmDash at runtime), for example:
|
|
42
|
+
- `/privacy`
|
|
43
|
+
- A full **`https://…`** URL, for example:
|
|
44
|
+
- `https://example.com/privacy`
|
|
45
|
+
- **Not accepted**:
|
|
46
|
+
- `http://…`
|
|
47
|
+
- `example.com/privacy` (missing scheme)
|
|
48
|
+
- `//example.com/privacy` (protocol-relative)
|
|
49
|
+
- paths without a leading slash like `privacy`
|
|
50
|
+
- **Behavior**:
|
|
51
|
+
- Controls where the “Privacy policy” link in the banner opens.
|
|
52
|
+
- Does not change consent cookie format or script loading.
|
|
53
|
+
|
|
54
|
+
### Cookie policy (optional) — path or https URL
|
|
55
|
+
|
|
56
|
+
- **What it is**: Optional link to a separate cookie policy.
|
|
57
|
+
- **Allowed inputs**: same rules as the privacy policy field.
|
|
58
|
+
- **Example**: `/cookies` or `https://example.com/cookies`
|
|
59
|
+
- **Behavior**:
|
|
60
|
+
- When set, the banner shows an additional “Cookie policy” link.
|
|
61
|
+
- When blank, no cookie-policy link is shown.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Consent versioning
|
|
66
|
+
|
|
67
|
+
### Policy / consent version
|
|
68
|
+
|
|
69
|
+
- **What it is**: A version string stored into the consent cookie. When you change it, existing visitors are prompted again.
|
|
70
|
+
- **Example values**:
|
|
71
|
+
- `1`
|
|
72
|
+
- `2026-04-25`
|
|
73
|
+
- `v3`
|
|
74
|
+
- **Behavior**:
|
|
75
|
+
- EmPrivacy stores consent as a cookie like `{ v, a, m }` where `v` is your policy version and `a/m` represent analytics/marketing choices.
|
|
76
|
+
- If a visitor has an older cookie version (or no cookie), the banner will show again.
|
|
77
|
+
- Use this when you materially change your privacy/cookie policy text, tracking vendors, or categories.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Defaults and consent UX
|
|
82
|
+
|
|
83
|
+
### Strict defaults (require opt-in for analytics & marketing)
|
|
84
|
+
|
|
85
|
+
- **What it is**: Controls whether the default state of the banner toggles is **off** (opt-in) or **on** (opt-out).
|
|
86
|
+
- **Example**:
|
|
87
|
+
- Enabled: analytics + marketing start **off**
|
|
88
|
+
- Disabled: analytics + marketing start **on**
|
|
89
|
+
- **Behavior**:
|
|
90
|
+
- **Enabled**: The initial banner loads with analytics and marketing toggles **unchecked** by default.
|
|
91
|
+
- **Disabled**: The initial banner loads with analytics and marketing toggles **checked** by default.
|
|
92
|
+
- This only affects the initial default state before the visitor makes a choice; once a cookie is set, the stored choice is used.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Analytics settings
|
|
97
|
+
|
|
98
|
+
Analytics scripts only load after the visitor consents to **Analytics** (unless you hard-code scripts elsewhere in your site/theme, which you should avoid).
|
|
99
|
+
|
|
100
|
+
### Analytics platform
|
|
101
|
+
|
|
102
|
+
- **What it is**: Chooses where analytics scripts come from.
|
|
103
|
+
- **Options**:
|
|
104
|
+
- **Cloudflare Web Analytics**: loads Cloudflare’s beacon **after Analytics consent** (requires a site token).
|
|
105
|
+
- **None**: never loads third-party analytics scripts via EmPrivacy.
|
|
106
|
+
- **Custom**: loads your provided `https://` script URLs **after Analytics consent**.
|
|
107
|
+
- **Behavior**:
|
|
108
|
+
- Changing this alters which scripts are injected when Analytics consent is granted.
|
|
109
|
+
- This does not affect Marketing scripts (those are separate).
|
|
110
|
+
|
|
111
|
+
### Cloudflare Web Analytics site token
|
|
112
|
+
|
|
113
|
+
- **What it is**: The token Cloudflare gives you for your site under Cloudflare → Web Analytics.
|
|
114
|
+
- **Example**: a Cloudflare token string copied from your dashboard (do not add quotes).
|
|
115
|
+
- **Behavior**:
|
|
116
|
+
- When Analytics consent is granted and **Analytics platform = Cloudflare**, EmPrivacy injects Cloudflare’s standard beacon script with the `data-cf-beacon` attribute.
|
|
117
|
+
- If the token is blank, EmPrivacy will have nothing to inject for Cloudflare analytics even if consent is granted.
|
|
118
|
+
|
|
119
|
+
### Custom analytics script URLs (one https URL per line, not a `<script>` tag)
|
|
120
|
+
|
|
121
|
+
- **What it is**: A list of third-party analytics scripts to load after Analytics consent, when **Analytics platform = Custom**.
|
|
122
|
+
- **Format**: one full **`https://…`** URL per line (the script `src`), no HTML.
|
|
123
|
+
- **Example**:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
https://cdn.example.com/analytics.js
|
|
127
|
+
https://static.example.net/vendor/tracker.min.js
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- **Behavior**:
|
|
131
|
+
- When Analytics consent is granted, EmPrivacy injects each URL as `<script src="…">` into the document.
|
|
132
|
+
- When Analytics consent is denied, these scripts are not injected by EmPrivacy.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Marketing settings
|
|
137
|
+
|
|
138
|
+
Marketing scripts only load after the visitor consents to **Marketing**.
|
|
139
|
+
|
|
140
|
+
### Marketing script URLs (one https URL per line, not a `<script>` tag)
|
|
141
|
+
|
|
142
|
+
- **What it is**: A list of third-party marketing scripts to load after Marketing consent.
|
|
143
|
+
- **Format**: one full **`https://…`** URL per line (the script `src`), no HTML.
|
|
144
|
+
- **Example**:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
https://cdn.example.com/pixel.js
|
|
148
|
+
https://static.example.net/ads/retargeting.js
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- **Behavior**:
|
|
152
|
+
- When Marketing consent is granted, EmPrivacy injects each URL as `<script src="…">`.
|
|
153
|
+
- When Marketing consent is denied, these scripts are not injected by EmPrivacy.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Google integrations (optional)
|
|
158
|
+
|
|
159
|
+
### Google Consent Mode v2 (denied defaults in head; updates after choice)
|
|
160
|
+
|
|
161
|
+
- **What it is**: Enables Google Consent Mode v2 integration.
|
|
162
|
+
- **Behavior**:
|
|
163
|
+
- When enabled, EmPrivacy emits a “denied by default” consent configuration early (in `<head>`).
|
|
164
|
+
- After the visitor chooses, EmPrivacy calls `gtag("consent","update", …)` to reflect Analytics/Marketing choices.
|
|
165
|
+
- This is only meaningful if your site uses `gtag`/Google tags; you should validate behavior using Google tooling/docs.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Server-side logging (optional)
|
|
170
|
+
|
|
171
|
+
### Log consent choices to the server (minimal record; no IP stored)
|
|
172
|
+
|
|
173
|
+
- **What it is**: If enabled, EmPrivacy will send a minimal consent snapshot to the server when a visitor saves a choice.
|
|
174
|
+
- **Behavior**:
|
|
175
|
+
- When enabled, the browser sends a POST to the EmPrivacy record endpoint with:
|
|
176
|
+
- the current policy version
|
|
177
|
+
- whether analytics was allowed
|
|
178
|
+
- whether marketing was allowed
|
|
179
|
+
- The settings page will additionally show **Recent consent records** (up to 15), newest first.
|
|
180
|
+
- When disabled, EmPrivacy does not attempt to log consent server-side and the “Recent consent records” section will not appear.
|
|
181
|
+
|
package/docs/RELEASES.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# Releases and versioning
|
|
4
|
+
|
|
5
|
+
Published **npm** versions of [`@emplugins/emprivacy`](https://www.npmjs.com/package/@emplugins/emprivacy) follow **[Semantic Versioning 2.0.0](https://semver.org/)** (`MAJOR.MINOR.PATCH`).
|
|
6
|
+
|
|
7
|
+
**Toolchain:** **pnpm** + **[Changesets](https://github.com/changesets/changesets)** + GitHub Actions (`release.yml`). Packages publish to the **[emplugins](https://www.npmjs.com/org/emplugins)** npm org via `pnpm publish`. Source: [EmPlugins/EmPrivacy](https://github.com/EmPlugins/EmPrivacy).
|
|
8
|
+
|
|
9
|
+
## What each bump means
|
|
10
|
+
|
|
11
|
+
| Level | When to use it |
|
|
12
|
+
|--------|----------------|
|
|
13
|
+
| **PATCH** | Bug fixes and safe internal refactors; no intentional behavior or API contract change for integrators. |
|
|
14
|
+
| **MINOR** | New features, new optional admin fields, or additive exports; existing sites keep working without config changes unless they opt in. |
|
|
15
|
+
| **MAJOR** | Breaking changes for site authors or the plugin contract (e.g. renamed exports, changed hook shapes, cookie JSON shape, required EmDash peer range). |
|
|
16
|
+
|
|
17
|
+
**Pre-1.0 (`0.x.y`):** Per the semver spec, anything may change; in practice we still use **patch / minor / major** as above so upgrades are predictable. Treat **minor** bumps as the place we may ship breaking changes until `1.0.0`, and read the release notes before upgrading.
|
|
18
|
+
|
|
19
|
+
**Policy / consent version** (in the EmDash admin) is separate from package semver: it only re-prompts visitors when your legal text or choices change.
|
|
20
|
+
|
|
21
|
+
## Safe publishing
|
|
22
|
+
|
|
23
|
+
These guards keep published tarballs consistent with `package.json` and avoid shipping stale or missing `dist/` output.
|
|
24
|
+
|
|
25
|
+
- **`dist/` is not committed** — It is listed in `.gitignore`. Build artifacts are produced locally, in CI, and **immediately before publish** via `prepublishOnly`.
|
|
26
|
+
- **`prepublishOnly`** — Runs `sync:version` (keeps `src/version.ts` aligned with `package.json`), `typecheck`, `build`, `test`, **`verify:exports`**, and `pnpm audit`.
|
|
27
|
+
- **`kysely` override** — The dev-dependency `emdash` can resolve an older `kysely`; `pnpm.overrides` in `package.json` pins a **patched** Kysely so `pnpm audit` stays clean. See [docs/DEVELOPMENT.md](DEVELOPMENT.md).
|
|
28
|
+
- **Install range** — Pin consumers with semver as needed, e.g. `@emplugins/emprivacy@^1.0.0`.
|
|
29
|
+
|
|
30
|
+
Before publishing locally (usually unnecessary once CI is configured):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm run build
|
|
34
|
+
pnpm pack --dry-run
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Cutting a release (maintainers)
|
|
38
|
+
|
|
39
|
+
### EmDash compatibility (fully agent-driven)
|
|
40
|
+
|
|
41
|
+
In Cursor:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
update to latest emdash release
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Uses [`.cursor/skills/emdash-release/`](../.cursor/skills/emdash-release/SKILL.md) and [`.cursor/emdash-release.json`](../.cursor/emdash-release.json): conformance → compat PR → Version Packages merge → `pnpm release:publish` (npm + GitHub Release). Details: [maintainer-release.md](./maintainer-release.md).
|
|
48
|
+
|
|
49
|
+
### Automated feature release (Changesets)
|
|
50
|
+
|
|
51
|
+
1. On a feature PR, run `pnpm changeset` and commit the generated file under `.changeset/`.
|
|
52
|
+
2. Merge to `main`. GitHub Actions opens a **Version Packages** PR when changesets are pending.
|
|
53
|
+
3. Merge the Version Packages PR. CI runs `pnpm release:publish` and creates a GitHub Release.
|
|
54
|
+
|
|
55
|
+
Requires **`NPM_TOKEN`** secret on the repo (publish rights for `@emplugins/emprivacy` on the [emplugins](https://www.npmjs.com/org/emplugins) org).
|
|
56
|
+
|
|
57
|
+
### Local (fallback)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pnpm install
|
|
61
|
+
pnpm changeset # on feature branch
|
|
62
|
+
pnpm changeset version # on main after merge
|
|
63
|
+
pnpm release:publish # sync, build, test, verify, audit, publish
|
|
64
|
+
git push --follow-tags
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Tags
|
|
68
|
+
|
|
69
|
+
Release tags use the **`v` prefix** (e.g. `v0.3.1`) via Changesets / GitHub Releases.
|
|
70
|
+
|
|
71
|
+
## EmDash compatibility
|
|
72
|
+
|
|
73
|
+
See [EMDASH_COMPAT.md](../EMDASH_COMPAT.md) for tested upstream versions and upgrade playbook.
|
|
74
|
+
|
|
75
|
+
## Consumers
|
|
76
|
+
|
|
77
|
+
Pin with a range that matches your risk tolerance, for example:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pnpm add @emplugins/emprivacy@^1.0.0
|
|
81
|
+
```
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# Unreleased
|
|
4
|
+
|
|
5
|
+
# @emplugins/emprivacy v1.0.0 (pending Version Packages)
|
|
6
|
+
|
|
7
|
+
## Breaking
|
|
8
|
+
|
|
9
|
+
- **npm package renamed** — Install and import **`@emplugins/emprivacy`** ( [emplugins](https://www.npmjs.com/org/emplugins) org ). Legacy unscoped `emprivacy` is no longer the publish target.
|
|
10
|
+
- **Sandbox entrypoint** — Descriptor uses `@emplugins/emprivacy/sandbox` (update only if you referenced the old entry string directly).
|
|
11
|
+
|
|
12
|
+
## Unchanged
|
|
13
|
+
|
|
14
|
+
- Runtime plugin id `emprivacy`, cookie `emprivacy_cc`, and API routes.
|
|
15
|
+
- Source repository: [EmPlugins/EmPrivacy](https://github.com/EmPlugins/EmPrivacy).
|
|
16
|
+
|
|
17
|
+
# emprivacy v0.3.0
|
|
18
|
+
|
|
19
|
+
## Changes
|
|
20
|
+
|
|
21
|
+
- **EmDash `>=0.14.0` required** — peer and dev dependency minimum raised from `^0.9.0`. Sites on EmDash 0.9–0.13 should stay on **emprivacy 0.2.x**.
|
|
22
|
+
- **Plugin entry** — `src/sandbox-entry.ts` now default-exports a bare `{ hooks, routes } satisfies SandboxedPlugin` object (types from `emdash/plugin`), matching EmDash 0.13+ standard-format plugins and `@emdash-cms/plugin-audit-log`. No runtime `definePlugin()` import.
|
|
23
|
+
- **CI** — matrix targets **EmDash `0.14.0`**.
|
|
24
|
+
- **Kysely override** — Bumped to **`0.29.2`** so `npm audit` stays clean with `emdash@0.14.x` (see [docs/DEVELOPMENT.md](DEVELOPMENT.md)).
|
|
25
|
+
|
|
26
|
+
# emprivacy v0.2.1
|
|
27
|
+
|
|
28
|
+
## Changes
|
|
29
|
+
|
|
30
|
+
- **Repository** — Canonical GitHub URLs now use **[EmPlugins/EmPrivacy](https://github.com/EmPlugins/EmPrivacy)** (`package.json` `repository` / `bugs` / `homepage`, admin plugin settings doc link, and permalinks in this file). No runtime behavior change.
|
|
31
|
+
|
|
32
|
+
# emprivacy v0.1.6
|
|
33
|
+
|
|
34
|
+
## Changes
|
|
35
|
+
|
|
36
|
+
- Compatibility: CI and manual QA verified with **EmDash `0.7.0`**.
|
|
37
|
+
|
|
38
|
+
# emprivacy v0.1.5
|
|
39
|
+
|
|
40
|
+
## Changes
|
|
41
|
+
|
|
42
|
+
- Fix Cloudflare Web Analytics when consent is granted from the initial banner by reloading after persisting choices (ensures the beacon runs in a normal page lifecycle).
|
|
43
|
+
|
|
44
|
+
# emprivacy v0.1.4
|
|
45
|
+
|
|
46
|
+
## Changes
|
|
47
|
+
|
|
48
|
+
- **Re-open consent** — After the first choice, a floating **cookie** control (bottom-left) re-opens the consent panel. Changing choices and saving **reloads** the page so analytics/marketing script loading matches the new consent (including when revoking). Duplicate `<script src>` tags for the same URL on one page are avoided when possible.
|
|
49
|
+
- **Analytics platforms** — Admin **radio**: **Cloudflare Web Analytics** (default), **None**, or **Custom** script URLs. For Cloudflare, paste the **site token** from the dashboard; EmPrivacy injects `https://static.cloudflareinsights.com/beacon.min.js` with `defer` and `data-cf-beacon='{"token":"…"}'` after analytics consent. Legacy configs with only `analyticsScriptUrls` in KV are treated as **Custom**.
|
|
50
|
+
|
|
51
|
+
# emprivacy v0.1.3
|
|
52
|
+
|
|
53
|
+
## Changes
|
|
54
|
+
|
|
55
|
+
- Pin **Kysely** to a patched version via `overrides` so `npm audit` reports **0** high-severity issues from the `emdash` dev dependency tree (Kysely advisories).
|
|
56
|
+
- Add `npm run audit` to CI and to `prepublishOnly` / `preversion` so releases fail if new audit findings appear.
|
|
57
|
+
- New [docs/DEVELOPMENT.md](https://github.com/EmPlugins/EmPrivacy/blob/v0.1.3/docs/DEVELOPMENT.md) (dependency, audit, and deprecation context for maintainers).
|
|
58
|
+
|
|
59
|
+
# emprivacy v0.1.2
|
|
60
|
+
|
|
61
|
+
## Changes
|
|
62
|
+
|
|
63
|
+
- `verify:exports` script: fail the release if `main` / `exports` paths are missing from `dist/` after build.
|
|
64
|
+
- `publishConfig.access: "public"` for explicit npm visibility.
|
|
65
|
+
- Documented safe-publishing workflow in `docs/RELEASES.md`; CI runs `verify:exports` after `build`.
|
|
66
|
+
|
|
67
|
+
# emprivacy v0.1.1
|
|
68
|
+
|
|
69
|
+
## Changes
|
|
70
|
+
|
|
71
|
+
- Packaging/release safety improvements for npm publishing (publish-time checks + version sync).
|
|
72
|
+
- Added CI workflow to run `typecheck`, `test`, and `build` on PRs/pushes.
|
|
73
|
+
|
|
74
|
+
# emprivacy v0.1.0 — initial release
|
|
75
|
+
|
|
76
|
+
First published **npm** release of **EmPrivacy**, an open source [EmDash](https://github.com/emdash-cms/emdash) plugin for cookie consent, category-based choices (essential / analytics / marketing), and **client-side** loading of third-party scripts only after consent.
|
|
77
|
+
|
|
78
|
+
## Highlights
|
|
79
|
+
|
|
80
|
+
- **Banner + categories** — Visitors choose analytics and marketing; essential is informational.
|
|
81
|
+
- **Policy links** — Privacy (and optional cookie) policy as an EmDash **Page** path (e.g. `/privacy`) or external `https://` URL; paths resolved with EmDash `ctx.url()`.
|
|
82
|
+
- **Script gating** — Only `https://` script URLs you configure in admin; injected as `<script src>` after consent (no arbitrary admin HTML on the public site).
|
|
83
|
+
- **Consent cookie** — `emprivacy_cc` with JSON `{ v, a, m }` (policy/consent version, analytics, marketing).
|
|
84
|
+
- **Optional server logging** — `POST /_emdash/api/plugins/emprivacy/record` and recent records in admin (no IP in v1).
|
|
85
|
+
- **Optional Google Consent Mode v2** — Denied defaults in `<head>` and updates after choice (validate with [Google’s documentation](https://support.google.com/tagmanager/answer/13695607)).
|
|
86
|
+
|
|
87
|
+
## Requirements
|
|
88
|
+
|
|
89
|
+
- **EmDash** `^0.5.0` — test on the minor you deploy.
|
|
90
|
+
- **Trusted plugins** in `astro.config` (`plugins: []`); EmPrivacy needs injection/fragments (not sandbox-only marketplace mode). See [EmDash plugin overview](https://docs.emdashcms.com/plugins/overview/).
|
|
91
|
+
- **Node.js** `>= 20`.
|
|
92
|
+
|
|
93
|
+
## Install
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm install emprivacy@^0.1.0
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Register `emprivacyPlugin()` early in `emdash({ plugins: [...] })` and wire EmDash layout components (`EmDashHead`, body slots, etc.). Full quick start: [README](https://github.com/EmPlugins/EmPrivacy/blob/v0.1.0/README.md).
|
|
100
|
+
|
|
101
|
+
## Documentation
|
|
102
|
+
|
|
103
|
+
- [Getting started](https://github.com/EmPlugins/EmPrivacy/blob/v0.1.0/docs/GETTING_STARTED.md)
|
|
104
|
+
- [Testing / pre-deploy checklist](https://github.com/EmPlugins/EmPrivacy/blob/v0.1.0/docs/TESTING.md)
|
|
105
|
+
- [Releases & semver](https://github.com/EmPlugins/EmPrivacy/blob/v0.1.0/docs/RELEASES.md)
|
|
106
|
+
|
|
107
|
+
## Legal
|
|
108
|
+
|
|
109
|
+
EmPrivacy is a **technical** CMP-style building block. It is **not legal advice**. You remain responsible for notices, vendors, and compliance in your jurisdictions.
|
package/docs/TESTING.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
|
|
3
|
+
# Testing EmPrivacy before deploy
|
|
4
|
+
|
|
5
|
+
Testing is split into **automated** checks (CI-friendly) and **manual** checks that require a running EmDash site, because the plugin integrates with EmDash’s runtime, KV, storage, admin Block Kit, and public page pipeline.
|
|
6
|
+
|
|
7
|
+
## Automated (in this repo)
|
|
8
|
+
|
|
9
|
+
| Command | What it verifies |
|
|
10
|
+
|--------|-------------------|
|
|
11
|
+
| `npm run typecheck` | TypeScript types against `emdash` APIs |
|
|
12
|
+
| `npm run build` | Bundles ESM + declarations (`dist/`) |
|
|
13
|
+
| `npm test` | Unit tests for **pure** helpers in `src/config.ts` (validation, normalization, URL list parsing, JSON escaping) |
|
|
14
|
+
|
|
15
|
+
These scripts do **not** start EmDash or exercise `page:fragments`, admin routes, or the consent cookie in a browser. They catch regressions in config/save validation and packaging early.
|
|
16
|
+
|
|
17
|
+
## Manual integration QA (required before production)
|
|
18
|
+
|
|
19
|
+
Use a **staging** EmDash **`0.14.0+`** Astro app with `emprivacyPlugin()` in `plugins: []`, layout wires (`EmDashHead` / body components), and the same EmDash version you plan to ship.
|
|
20
|
+
|
|
21
|
+
Work through the checklist from the main [README](../README.md) (also copied below). Record pass/fail and browser + EmDash versions.
|
|
22
|
+
|
|
23
|
+
### Core flows
|
|
24
|
+
|
|
25
|
+
1. **Banner** — Incognito window: banner appears when there is no `emprivacy_cc` cookie or when **Policy / consent version** in admin does not match the cookie’s `v` field.
|
|
26
|
+
2. **Re-open consent** — After dismissing the banner, confirm a **cookie button** appears (bottom-left). Click it: the same options appear; **Save choices** (or Accept/Reject) reloads the page. After reload, **Network** should list analytics scripts only if analytics is on; turn analytics off, save, reload, and those scripts should not run. If you use **Cloudflare Web Analytics** in admin, after consent confirm `beacon.min.js` loads and the tag includes `data-cf-beacon` with your token.
|
|
27
|
+
3. **Strict defaults** — With strict mode on, deny non-essential and confirm configured analytics/marketing URLs do **not** appear in Network until the user accepts (or enables those categories in Customize).
|
|
28
|
+
4. **Persistence** — After accept, reload: banner stays closed; scripts load according to saved choices (Network tab).
|
|
29
|
+
5. **Admin** — EmPrivacy settings page loads, **Save** persists; public banner text and links match what you saved (after refresh / new request).
|
|
30
|
+
6. **Optional server log** — Enable “Log consent…”; submit consent; confirm a row appears under recent records and `POST /_emdash/api/plugins/emprivacy/record` succeeds (200, `{ ok: true }`) in Network.
|
|
31
|
+
7. **Optional Google Consent Mode** — Enable in admin; verify a denied-default snippet exists in `<head>` before interaction, and updates after choice (see [Google’s Consent Mode docs](https://support.google.com/tagmanager/answer/13695607)).
|
|
32
|
+
|
|
33
|
+
### Regression triggers
|
|
34
|
+
|
|
35
|
+
- Bump EmDash minor: re-run manual QA (plugin APIs and admin routing can change).
|
|
36
|
+
- Bump this plugin’s **npm semver** after changing hooks or cookie shape: re-check banner and cookie JSON. Release numbering policy: [RELEASES.md](./RELEASES.md).
|
|
37
|
+
|
|
38
|
+
## CI suggestion
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm ci
|
|
42
|
+
npm run typecheck
|
|
43
|
+
npm run build
|
|
44
|
+
npm test
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Future improvements (not in v1)
|
|
48
|
+
|
|
49
|
+
- **Integration tests** against EmDash’s `adaptSandboxEntry` + mock `PluginContext` (heavy; depends on EmDash test utilities if exposed).
|
|
50
|
+
- **E2E** (Playwright) against a minimal EmDash fixture app in CI (slower, higher maintenance).
|
|
51
|
+
|
|
52
|
+
For most teams, **automated unit tests + staging manual QA** is the right balance.
|
|
53
|
+
|