mirror of
https://github.com/Anarios/return-youtube-dislike.git
synced 2026-10-27 23:31:06 +01:00
Exclude maintainer notes from public source packages
This commit is contained in:
+15
-1
@@ -5,9 +5,21 @@
|
|||||||
# Website node modules and build output
|
# Website node modules and build output
|
||||||
Website/package-lock.json
|
Website/package-lock.json
|
||||||
|
|
||||||
# AI assistant artifacts
|
# Private maintainer guidance and local workspace state
|
||||||
|
/.private/
|
||||||
|
.codex/
|
||||||
|
.agents/
|
||||||
|
AGENTS.md
|
||||||
|
AGENTS.local.md
|
||||||
|
AGENTS.override.md
|
||||||
.claude/
|
.claude/
|
||||||
CLAUDE.md
|
CLAUDE.md
|
||||||
|
# Retired private-document locations; do not reintroduce them into public source.
|
||||||
|
/Docs/SSH_ACCESS.md
|
||||||
|
/Docs/DiscussionApi.md
|
||||||
|
/Docs/DiscussionValidation.md
|
||||||
|
/AMO_SUBMISSION_NOTES.md
|
||||||
|
|
||||||
Website/.editorconfig
|
Website/.editorconfig
|
||||||
Website/node_modules
|
Website/node_modules
|
||||||
Website/.nuxt
|
Website/.nuxt
|
||||||
@@ -33,6 +45,8 @@ yarn-error.log*
|
|||||||
*.sw*
|
*.sw*
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
|
.pnpm-store/
|
||||||
|
.pnpm-store/
|
||||||
|
|
||||||
# Build files
|
# Build files
|
||||||
Extensions/combined/bundled-content-script.js
|
Extensions/combined/bundled-content-script.js
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
# AMO 4.0.5 Submission Notes
|
|
||||||
|
|
||||||
## Files to upload
|
|
||||||
|
|
||||||
- Add-on package: `return-youtube-dislike-firefox-4.0.5.zip`
|
|
||||||
- Source package: `return-youtube-dislike-source-4.0.5.zip`
|
|
||||||
- Privacy policy: copy `Docs/Privacy Policy` into the AMO listing privacy-policy field.
|
|
||||||
|
|
||||||
## Backend deployment prerequisite
|
|
||||||
|
|
||||||
Deploy the matching backend entitlement change **before releasing extension 4.0.5** or publishing its privacy policy.
|
|
||||||
The account flow must request only currently entitled Patreon tier IDs for eligibility, with no membership amount,
|
|
||||||
charge-date/status, lifetime-payment, or patron-status attributes. Verify that behavior and a fresh reviewer-account
|
|
||||||
login against the deployed backend. The source changes and these notes do not establish that the live backend has
|
|
||||||
already been updated.
|
|
||||||
|
|
||||||
## Notes to reviewer
|
|
||||||
|
|
||||||
Version 4.0.5 addresses rejection reference `a424a6ef-1172-4c6c-8028-22187c194255` and the earlier source-code
|
|
||||||
review concerns.
|
|
||||||
|
|
||||||
The Firefox manifest now uses Firefox's built-in data-collection consent system and requires Firefox 140 or later. It
|
|
||||||
retains the published add-on ID `{762f9885-5a13-4abd-9c77-433dcd38b8fd}` and declares these required data categories:
|
|
||||||
|
|
||||||
- `personallyIdentifyingInfo`: a persistent random installation `userId` is registered with the Return YouTube Dislike
|
|
||||||
API and is included with vote submissions. Optional sign-in also processes provider account identifiers, name,
|
|
||||||
profile image, and email when returned by GitHub under this category. Patreon does not request or return email.
|
|
||||||
- `browsingActivity`: the current YouTube `videoId` identifies the video page being viewed and is sent for dislike
|
|
||||||
lookups and related analytics.
|
|
||||||
- `websiteContent`: the current YouTube `videoId` and, when available, visible `likeCount` are sent to the API to obtain
|
|
||||||
and improve the dislike estimate.
|
|
||||||
- `websiteActivity`: a user-initiated Like, Dislike, or vote removal is sent as the vote `value` with the `videoId` and
|
|
||||||
random `userId`.
|
|
||||||
|
|
||||||
The optional Patreon/GitHub account feature declares `authenticationInfo`. The matching backend determines Patreon
|
|
||||||
access from currently entitled tier IDs, without requesting or using membership amounts, charge dates or status,
|
|
||||||
lifetime payments, or patron status. Firefox requests authentication permission directly from the corresponding
|
|
||||||
sign-in click. Denying it produces no OAuth, session-verification, or premium Bearer-token traffic. Removing it clears
|
|
||||||
the account session, tears down active premium analytics, and blocks
|
|
||||||
later account requests. Delayed login and verification responses cannot restore a revoked session. Core dislike counts
|
|
||||||
continue to work. Browser sync may synchronize extension settings, identifiers, and account sessions when enabled.
|
|
||||||
|
|
||||||
Treating tier IDs as account entitlements covered by account identity and authentication declarations is our data-category
|
|
||||||
interpretation; Mozilla has not approved this classification. Paid access remains disclosed in the listing. The
|
|
||||||
`financialAndPaymentInfo` category is omitted because the matching backend no longer requests or processes the financial
|
|
||||||
and payment attributes used by the earlier implementation. Removing an obsolete financial-data grant alone does not
|
|
||||||
sign the user out; revoking authentication consent does.
|
|
||||||
|
|
||||||
Firefox private-window access is disabled so private browsing data is not retained. The popup no longer makes an
|
|
||||||
unrelated remote version check or server-status probe, and packaged extension pages no longer request remote fonts.
|
|
||||||
|
|
||||||
The supplied source archive contains the lockfile, exact production inputs, and build instructions. From its root,
|
|
||||||
install Node.js 22.17.0 and npm 10.8.2, then run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
node scripts/build-firefox-source.mjs
|
|
||||||
```
|
|
||||||
|
|
||||||
The generated comparison directory is `Extensions/combined/dist/firefox`. The build script checks the version,
|
|
||||||
manifest consent contract, required `menu-fixer.js`, bundle size, absence of source-map references, and source-input
|
|
||||||
receipt. Dependencies are installed only through npm from the npm registry.
|
|
||||||
|
|
||||||
## Functional review path
|
|
||||||
|
|
||||||
1. Install in a fresh Firefox 140-or-newer profile and accept the required data categories.
|
|
||||||
2. Open a public YouTube video and confirm the dislike estimate appears.
|
|
||||||
3. Open the extension popup. Decline either Patreon or GitHub sign-in consent and confirm the account remains signed
|
|
||||||
out while ordinary dislike counts continue working.
|
|
||||||
4. Grant the optional authentication permission and sign in with the supplied reviewer account. Exercise the premium
|
|
||||||
analytics panel using that account's active premium access.
|
|
||||||
5. Revoke authentication data under `about:addons` > Return YouTube Dislike > Permissions and data. Confirm
|
|
||||||
the account session ends and no premium panel appears on subsequent navigation or after restarting Firefox.
|
|
||||||
|
|
||||||
## Listing and reviewer access
|
|
||||||
|
|
||||||
Add this disclosure to the listing description:
|
|
||||||
|
|
||||||
> Return YouTube Dislike sends the current YouTube video ID and visible like count to its API to display dislike
|
|
||||||
> estimates. Optional vote submissions include a persistent random installation ID and your selected vote. Optional
|
|
||||||
> Patreon/GitHub sign-in processes account and membership information. Premium analytics has eligibility requirements,
|
|
||||||
> including paid Patreon membership tiers. Core dislike counts are free. Firefox asks for required data consent during installation or update and
|
|
||||||
> requests optional account-data consent when you sign in.
|
|
||||||
|
|
||||||
Before submission, deploy the backend entitlement change and complimentary-access grant, then verify a fresh login with the dedicated
|
|
||||||
Patreon test account. Supply that account's login details in AMO's **Notes for Reviewers**, as described in the
|
|
||||||
[submission guide](https://extensionworkshop.com/documentation/publish/submitting-an-add-on/). Mozilla requires
|
|
||||||
reviewer access to account-only functionality. Do not place credentials in this file or in the source archive.
|
|
||||||
Confirm the listing discloses paid functionality and includes the updated privacy policy.
|
|
||||||
|
|
||||||
Include these instructions with the login details:
|
|
||||||
|
|
||||||
> This is a dedicated Patreon test account with complimentary premium access granted by our backend. No paid
|
|
||||||
> subscription is needed. In the extension popup, choose Log in with Patreon, accept the optional account-data
|
|
||||||
> permission prompt, and complete Patreon authorization using the supplied test account. Open a YouTube video and
|
|
||||||
> its premium analytics. Complimentary access is available through October 5, 2026 (UTC); contact us if the review
|
|
||||||
> requires an extension.
|
|
||||||
|
|
||||||
## Policy references
|
|
||||||
|
|
||||||
- [Built-in data consent and data categories](https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/)
|
|
||||||
- [Submission and data-transmission requirements](https://extensionworkshop.com/documentation/publish/add-on-policies/)
|
|
||||||
- [Source-code submission](https://extensionworkshop.com/documentation/publish/source-code-submission/)
|
|
||||||
|
|
||||||
Temporary developer installs silently grant required permissions and do not prove the installation/update consent
|
|
||||||
prompt. Test that prompt using a packaged install in a disposable Firefox Developer Edition or Nightly profile.
|
|
||||||
@@ -13,7 +13,6 @@ const EXPECTED_NODE = "v22.17.0";
|
|||||||
const EXPECTED_NPM = "10.8.2";
|
const EXPECTED_NPM = "10.8.2";
|
||||||
const ARTIFACT_VERIFIER_PATH = "Extensions/e2e/verify-extension-artifact.js";
|
const ARTIFACT_VERIFIER_PATH = "Extensions/e2e/verify-extension-artifact.js";
|
||||||
const EXTRA_SOURCE_FILES = Object.freeze([
|
const EXTRA_SOURCE_FILES = Object.freeze([
|
||||||
"AMO_SUBMISSION_NOTES.md",
|
|
||||||
"Docs/Privacy Policy",
|
"Docs/Privacy Policy",
|
||||||
ARTIFACT_VERIFIER_PATH,
|
ARTIFACT_VERIFIER_PATH,
|
||||||
"README_AMO_SOURCE.md",
|
"README_AMO_SOURCE.md",
|
||||||
@@ -300,7 +299,6 @@ async function packageRelease(outputDirectory) {
|
|||||||
);
|
);
|
||||||
verifyBuildReceipt();
|
verifyBuildReceipt();
|
||||||
for (const [source, destination] of [
|
for (const [source, destination] of [
|
||||||
["AMO_SUBMISSION_NOTES.md", "AMO_SUBMISSION_NOTES.md"],
|
|
||||||
["README_AMO_SOURCE.md", "README_AMO_SOURCE.md"],
|
["README_AMO_SOURCE.md", "README_AMO_SOURCE.md"],
|
||||||
["Docs/Privacy Policy", "PRIVACY_POLICY.md"],
|
["Docs/Privacy Policy", "PRIVACY_POLICY.md"],
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -103,3 +103,35 @@ test("source allowlist includes the standalone build and packaging tools but exc
|
|||||||
);
|
);
|
||||||
expect(files.some((name) => /\.spec\.|Extensions\/UserScript|node_modules|\.env/.test(name))).toBe(false);
|
expect(files.some((name) => /\.spec\.|Extensions\/UserScript|node_modules|\.env/.test(name))).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("source archive excludes private maintainer notes even when they exist beside public inputs", async () => {
|
||||||
|
const root = path.resolve(__dirname, "..");
|
||||||
|
const publicFiles = buildSourceFileList(root);
|
||||||
|
for (const name of publicFiles) {
|
||||||
|
const destination = path.join(temporary, name);
|
||||||
|
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
||||||
|
fs.copyFileSync(path.join(root, name), destination);
|
||||||
|
}
|
||||||
|
const privateFiles = [
|
||||||
|
"AGENTS.md",
|
||||||
|
"AMO_SUBMISSION_NOTES.md",
|
||||||
|
"Docs/SSH_ACCESS.md",
|
||||||
|
"Docs/DiscussionApi.md",
|
||||||
|
"Docs/DiscussionValidation.md",
|
||||||
|
".private/operations/SSH_ACCESS.md",
|
||||||
|
".agents/local.md",
|
||||||
|
];
|
||||||
|
for (const name of privateFiles) {
|
||||||
|
const destination = path.join(temporary, name);
|
||||||
|
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
||||||
|
fs.writeFileSync(destination, "PRIVATE_MAINTAINER_FIXTURE");
|
||||||
|
}
|
||||||
|
const files = buildSourceFileList(temporary);
|
||||||
|
for (const name of privateFiles) expect(files).not.toContain(name);
|
||||||
|
const archive = path.join(temporary, "source.zip");
|
||||||
|
await createZip(archive, new Map(files.map((name) => [name, fs.readFileSync(path.join(temporary, name))])));
|
||||||
|
const entries = readZipFiles(archive);
|
||||||
|
for (const name of privateFiles) expect(entries.has(name)).toBe(false);
|
||||||
|
for (const content of entries.values())
|
||||||
|
expect(content.includes(Buffer.from("PRIVATE_MAINTAINER_FIXTURE"))).toBe(false);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user