@zigrivers/scaffold 3.8.0 → 3.9.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.
Files changed (70) hide show
  1. package/README.md +73 -8
  2. package/content/knowledge/browser-extension/browser-extension-architecture.md +195 -0
  3. package/content/knowledge/browser-extension/browser-extension-content-scripts.md +264 -0
  4. package/content/knowledge/browser-extension/browser-extension-conventions.md +156 -0
  5. package/content/knowledge/browser-extension/browser-extension-cross-browser.md +229 -0
  6. package/content/knowledge/browser-extension/browser-extension-dev-environment.md +247 -0
  7. package/content/knowledge/browser-extension/browser-extension-manifest.md +220 -0
  8. package/content/knowledge/browser-extension/browser-extension-project-structure.md +183 -0
  9. package/content/knowledge/browser-extension/browser-extension-requirements.md +107 -0
  10. package/content/knowledge/browser-extension/browser-extension-security.md +202 -0
  11. package/content/knowledge/browser-extension/browser-extension-service-workers.md +265 -0
  12. package/content/knowledge/browser-extension/browser-extension-store-submission.md +155 -0
  13. package/content/knowledge/browser-extension/browser-extension-testing.md +270 -0
  14. package/content/knowledge/data-pipeline/data-pipeline-architecture.md +175 -0
  15. package/content/knowledge/data-pipeline/data-pipeline-batch-patterns.md +263 -0
  16. package/content/knowledge/data-pipeline/data-pipeline-conventions.md +176 -0
  17. package/content/knowledge/data-pipeline/data-pipeline-dev-environment.md +350 -0
  18. package/content/knowledge/data-pipeline/data-pipeline-orchestration.md +291 -0
  19. package/content/knowledge/data-pipeline/data-pipeline-project-structure.md +257 -0
  20. package/content/knowledge/data-pipeline/data-pipeline-quality.md +324 -0
  21. package/content/knowledge/data-pipeline/data-pipeline-requirements.md +145 -0
  22. package/content/knowledge/data-pipeline/data-pipeline-schema-management.md +295 -0
  23. package/content/knowledge/data-pipeline/data-pipeline-security.md +326 -0
  24. package/content/knowledge/data-pipeline/data-pipeline-streaming-patterns.md +280 -0
  25. package/content/knowledge/data-pipeline/data-pipeline-testing.md +406 -0
  26. package/content/knowledge/ml/ml-architecture.md +172 -0
  27. package/content/knowledge/ml/ml-conventions.md +209 -0
  28. package/content/knowledge/ml/ml-dev-environment.md +299 -0
  29. package/content/knowledge/ml/ml-experiment-tracking.md +285 -0
  30. package/content/knowledge/ml/ml-model-evaluation.md +256 -0
  31. package/content/knowledge/ml/ml-observability.md +253 -0
  32. package/content/knowledge/ml/ml-project-structure.md +216 -0
  33. package/content/knowledge/ml/ml-requirements.md +138 -0
  34. package/content/knowledge/ml/ml-security.md +188 -0
  35. package/content/knowledge/ml/ml-serving-patterns.md +243 -0
  36. package/content/knowledge/ml/ml-testing.md +301 -0
  37. package/content/knowledge/ml/ml-training-patterns.md +269 -0
  38. package/content/methodology/browser-extension-overlay.yml +82 -0
  39. package/content/methodology/data-pipeline-overlay.yml +70 -0
  40. package/content/methodology/ml-overlay.yml +70 -0
  41. package/dist/cli/commands/init.d.ts +13 -0
  42. package/dist/cli/commands/init.d.ts.map +1 -1
  43. package/dist/cli/commands/init.js +122 -2
  44. package/dist/cli/commands/init.js.map +1 -1
  45. package/dist/cli/commands/init.test.js +120 -0
  46. package/dist/cli/commands/init.test.js.map +1 -1
  47. package/dist/config/schema.d.ts +864 -48
  48. package/dist/config/schema.d.ts.map +1 -1
  49. package/dist/config/schema.js +53 -0
  50. package/dist/config/schema.js.map +1 -1
  51. package/dist/config/schema.test.js +166 -3
  52. package/dist/config/schema.test.js.map +1 -1
  53. package/dist/core/assembly/overlay-loader.test.js +33 -0
  54. package/dist/core/assembly/overlay-loader.test.js.map +1 -1
  55. package/dist/e2e/project-type-overlays.test.d.ts +2 -2
  56. package/dist/e2e/project-type-overlays.test.js +499 -33
  57. package/dist/e2e/project-type-overlays.test.js.map +1 -1
  58. package/dist/types/config.d.ts +10 -1
  59. package/dist/types/config.d.ts.map +1 -1
  60. package/dist/wizard/questions.d.ts +17 -1
  61. package/dist/wizard/questions.d.ts.map +1 -1
  62. package/dist/wizard/questions.js +72 -1
  63. package/dist/wizard/questions.js.map +1 -1
  64. package/dist/wizard/questions.test.js +135 -0
  65. package/dist/wizard/questions.test.js.map +1 -1
  66. package/dist/wizard/wizard.d.ts +13 -0
  67. package/dist/wizard/wizard.d.ts.map +1 -1
  68. package/dist/wizard/wizard.js +17 -1
  69. package/dist/wizard/wizard.js.map +1 -1
  70. package/package.json +1 -1
@@ -0,0 +1,220 @@
1
+ ---
2
+ name: browser-extension-manifest
3
+ description: Manifest V3 schema, permissions declarations, host_permissions, content_scripts configuration, and background service_worker setup
4
+ topics: [browser-extension, manifest, manifest-v3, permissions, content-scripts, service-worker, host-permissions]
5
+ ---
6
+
7
+ The `manifest.json` is the contract between your extension and the browser. Every capability your extension uses must be declared here before it can be used. Manifest V3 (MV3) is the current standard, having replaced Manifest V2 (MV2) in Chrome. Understanding the MV3 schema in depth prevents runtime errors, store rejections, and security review failures.
8
+
9
+ ## Summary
10
+
11
+ Manifest V3 separates `permissions` (API access) from `host_permissions` (URL access), requires a service worker instead of a background page, restricts remote code execution, and requires `web_accessible_resources` to include a `matches` field. Declare the minimum required permissions. Use `optional_permissions` and `optional_host_permissions` for features not needed by all users. The `action` key replaces `browser_action`. All `content_scripts` must declare their `matches` precisely.
12
+
13
+ ## Deep Guidance
14
+
15
+ ### Minimal Valid Manifest V3
16
+
17
+ ```json
18
+ {
19
+ "manifest_version": 3,
20
+ "name": "__MSG_extensionName__",
21
+ "version": "1.0.0",
22
+ "description": "__MSG_extensionDescription__",
23
+ "short_name": "__MSG_extensionShortName__",
24
+ "default_locale": "en",
25
+
26
+ "action": {
27
+ "default_popup": "popup/index.html",
28
+ "default_icon": {
29
+ "16": "icons/icon-16.png",
30
+ "32": "icons/icon-32.png",
31
+ "48": "icons/icon-48.png",
32
+ "128": "icons/icon-128.png"
33
+ },
34
+ "default_title": "__MSG_actionTitle__"
35
+ },
36
+
37
+ "background": {
38
+ "service_worker": "background.js",
39
+ "type": "module"
40
+ },
41
+
42
+ "content_scripts": [
43
+ {
44
+ "matches": ["https://*.example.com/*"],
45
+ "js": ["content.js"],
46
+ "css": ["content.css"],
47
+ "run_at": "document_idle"
48
+ }
49
+ ],
50
+
51
+ "permissions": ["storage", "alarms"],
52
+ "host_permissions": ["https://*.example.com/*"],
53
+
54
+ "options_page": "options/index.html",
55
+
56
+ "icons": {
57
+ "16": "icons/icon-16.png",
58
+ "32": "icons/icon-32.png",
59
+ "48": "icons/icon-48.png",
60
+ "128": "icons/icon-128.png"
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### permissions Field
66
+
67
+ `permissions` grants access to Chrome extension APIs. Declare only the APIs your extension actually calls:
68
+
69
+ | Permission | Grants access to |
70
+ |---|---|
71
+ | `storage` | `chrome.storage.local`, `chrome.storage.sync`, `chrome.storage.session` |
72
+ | `alarms` | `chrome.alarms` (recurring background tasks) |
73
+ | `tabs` | `chrome.tabs` (tab URL, title, favicon — triggers install warning) |
74
+ | `activeTab` | Active tab URL/content on user gesture (no install warning) |
75
+ | `contextMenus` | `chrome.contextMenus` (right-click menu items) |
76
+ | `notifications` | `chrome.notifications` |
77
+ | `identity` | `chrome.identity` (OAuth2 flow) |
78
+ | `webRequest` | `chrome.webRequest` (intercept requests — high scrutiny) |
79
+ | `declarativeNetRequest` | `chrome.declarativeNetRequest` (rule-based request blocking) |
80
+ | `scripting` | `chrome.scripting.executeScript` (inject scripts programmatically) |
81
+ | `history` | `chrome.history` (browsing history access) |
82
+ | `bookmarks` | `chrome.bookmarks` |
83
+ | `cookies` | `chrome.cookies` |
84
+ | `downloads` | `chrome.downloads` |
85
+
86
+ **activeTab vs tabs:** Prefer `activeTab` over `tabs`. `activeTab` grants temporary access to the current tab URL and content only when the user explicitly invokes the extension (toolbar click, keyboard shortcut, context menu). It does not trigger an install-time warning and does not grant persistent access. Use `tabs` only when you need to enumerate all tabs or access tab information without a user gesture.
87
+
88
+ ### host_permissions Field
89
+
90
+ `host_permissions` controls which URLs the extension can access via content scripts, `fetch()` from the background, or `chrome.tabs.executeScript()`.
91
+
92
+ ```json
93
+ "host_permissions": [
94
+ "https://api.myservice.com/*",
95
+ "https://*.example.com/*"
96
+ ]
97
+ ```
98
+
99
+ **Match pattern syntax:**
100
+
101
+ - `https://example.com/*` — Only `example.com`, HTTPS only.
102
+ - `https://*.example.com/*` — All subdomains of `example.com`, HTTPS only.
103
+ - `https://example.com/path/*` — Only paths under `/path/`.
104
+ - `*://example.com/*` — Both HTTP and HTTPS.
105
+ - `<all_urls>` — Every URL. Triggers maximum-severity install warning. Avoid unless the use case is genuinely broad (ad blockers, password managers, reading mode).
106
+
107
+ **Optional host permissions** reduce the install-time permission scope and request access contextually:
108
+
109
+ ```json
110
+ "optional_host_permissions": ["https://*.github.com/*"]
111
+ ```
112
+
113
+ ```typescript
114
+ // Request at runtime when the user enables the GitHub integration
115
+ const granted = await chrome.permissions.request({
116
+ origins: ['https://*.github.com/*'],
117
+ });
118
+ ```
119
+
120
+ ### content_scripts Configuration
121
+
122
+ Content scripts are injected into matching pages according to their declaration in `manifest.json`.
123
+
124
+ ```json
125
+ "content_scripts": [
126
+ {
127
+ "matches": ["https://*.example.com/*"],
128
+ "exclude_matches": ["https://example.com/admin/*"],
129
+ "js": ["content.js"],
130
+ "css": ["content.css"],
131
+ "run_at": "document_idle",
132
+ "all_frames": false,
133
+ "world": "ISOLATED"
134
+ }
135
+ ]
136
+ ```
137
+
138
+ **run_at options:**
139
+ - `"document_start"` — Injected before any DOM is built. Useful for blocking scripts from loading. High risk of performance impact.
140
+ - `"document_end"` — Injected after DOM is ready but before sub-resources (images, stylesheets) finish loading.
141
+ - `"document_idle"` — (Default) Injected after `DOMContentLoaded` and when the page is "idle." Best choice for most extensions.
142
+
143
+ **world options (MV3 Chrome 102+):**
144
+ - `"ISOLATED"` — (Default) Content script runs in the isolated JavaScript world. Cannot access page's JavaScript variables.
145
+ - `"MAIN"` — Content script runs in the page's JavaScript world. Can access page variables and global state. Use only when you must interact with the page's JavaScript API. Increases security risk.
146
+
147
+ **all_frames:** Set to `true` to inject into iframes on matching pages. Default is `false`. Only enable if the extension's functionality is needed within iframes.
148
+
149
+ **Programmatic injection with chrome.scripting:**
150
+
151
+ For content scripts that should only be injected on user demand (not all matching pages):
152
+
153
+ ```typescript
154
+ // Background — inject only when user requests it
155
+ chrome.action.onClicked.addListener(async (tab) => {
156
+ if (!tab.id) return;
157
+ await chrome.scripting.executeScript({
158
+ target: { tabId: tab.id },
159
+ files: ['content.js'],
160
+ });
161
+ await chrome.scripting.insertCSS({
162
+ target: { tabId: tab.id },
163
+ files: ['content.css'],
164
+ });
165
+ });
166
+ ```
167
+
168
+ Programmatic injection requires the `scripting` permission and appropriate `host_permissions` for the target URL.
169
+
170
+ ### background.service_worker
171
+
172
+ ```json
173
+ "background": {
174
+ "service_worker": "background.js",
175
+ "type": "module"
176
+ }
177
+ ```
178
+
179
+ `"type": "module"` enables ES module syntax (`import`/`export`) in the service worker. Recommended for TypeScript projects since the bundler outputs ES modules. Without this field, the service worker is treated as a classic script.
180
+
181
+ **MV2 to MV3 migration notes:**
182
+
183
+ - MV2 `"background": { "scripts": [...] }` → MV3 `"background": { "service_worker": "..." }`.
184
+ - MV2 background pages are persistent. MV3 service workers are not. State in global variables will be lost.
185
+ - `chrome.browserAction` → `chrome.action`.
186
+ - `chrome.pageAction` → `chrome.action` (with `show_matches` / `hide_matches`).
187
+ - Remote code execution (`eval`, remote `<script>` tags, `new Function()` from remote strings) is prohibited in MV3.
188
+
189
+ ### web_accessible_resources
190
+
191
+ Resources that content scripts or host pages need to load from the extension package:
192
+
193
+ ```json
194
+ "web_accessible_resources": [
195
+ {
196
+ "resources": ["images/*.png", "fonts/*.woff2"],
197
+ "matches": ["https://*.example.com/*"]
198
+ },
199
+ {
200
+ "resources": ["sandbox.html"],
201
+ "matches": ["<all_urls>"]
202
+ }
203
+ ]
204
+ ```
205
+
206
+ The `matches` field is required in MV3 (optional in MV2). Restricting `matches` to only the pages that need the resources limits the attack surface — arbitrary pages cannot load the extension's resources unless they match. Use `"<all_urls>"` only for resources that genuinely need to be accessible from any page.
207
+
208
+ Access declared resources in content scripts with `chrome.runtime.getURL('images/logo.png')`.
209
+
210
+ ### Version Management
211
+
212
+ ```json
213
+ "version": "1.4.2",
214
+ "version_name": "1.4.2 Beta"
215
+ ```
216
+
217
+ - `version` — Machine-readable four-part version used by the store for update detection. Must be strictly greater than the previous published version to be accepted as an update.
218
+ - `version_name` — Human-readable display name shown in the extensions management page. Optional; defaults to `version` if omitted.
219
+
220
+ Automate version synchronization between `manifest.json` and `package.json` with a build script that reads `package.json` version and writes it to `manifest.json` before building.
@@ -0,0 +1,183 @@
1
+ ---
2
+ name: browser-extension-project-structure
3
+ description: Directory layout for browser extensions covering src/popup, src/content, src/background, src/options, public/icons, and _locales
4
+ topics: [browser-extension, project-structure, file-organization, build, icons]
5
+ ---
6
+
7
+ Browser extension project structure must account for multiple compilation targets (one bundle per execution context), static assets that bypass the build pipeline, and locale files consumed by the WebExtensions runtime. A well-organized project structure makes build configuration straightforward, keeps context-specific code isolated, and prevents accidentally importing browser APIs that are unavailable in a given context.
8
+
9
+ ## Summary
10
+
11
+ Browser extension projects organize source code by execution context (`src/background/`, `src/content/`, `src/popup/`, `src/options/`), share cross-context code via `src/shared/`, serve static assets and icons from `public/`, store locale strings in `_locales/`, and output all built artifacts to `dist/`. The build tool (Vite or Webpack) is configured with multiple entry points — one per context. The `manifest.json` lives at the root and references compiled output paths.
12
+
13
+ ## Deep Guidance
14
+
15
+ ### Top-Level Directory Layout
16
+
17
+ ```
18
+ my-extension/
19
+ src/ # All TypeScript/JavaScript source
20
+ public/ # Static assets copied verbatim to dist/
21
+ _locales/ # WebExtensions i18n message files
22
+ manifest.json # Extension manifest (source of truth)
23
+ dist/ # Build output (gitignored)
24
+ tests/ # Unit and integration tests
25
+ scripts/ # Build and release helper scripts
26
+ package.json
27
+ tsconfig.json
28
+ vite.config.ts # (or webpack.config.ts)
29
+ ```
30
+
31
+ **Key decisions at this level:**
32
+ - `manifest.json` is a source file, not generated. Keep it at the root and have the build tool copy it to `dist/` with any environment-specific substitutions applied.
33
+ - `dist/` is always gitignored. It is a build artifact, not source.
34
+ - `public/` contains files that are copied as-is without processing — icons, web-accessible static HTML, third-party JS files that must not be bundled.
35
+
36
+ ### src/ — Source Organized by Execution Context
37
+
38
+ ```
39
+ src/
40
+ background/
41
+ index.ts # Service worker entry point
42
+ message-router.ts # Central message dispatch
43
+ handlers/
44
+ tab-handlers.ts
45
+ storage-handlers.ts
46
+ alarm-handlers.ts
47
+ alarms.ts # Alarm registration
48
+ install.ts # onInstalled handler (first-run setup)
49
+
50
+ content/
51
+ index.ts # Content script entry point
52
+ injectors/
53
+ overlay-injector.ts # Injects UI overlays into the host page
54
+ banner-injector.ts
55
+ observers/
56
+ dom-observer.ts # MutationObserver for dynamic pages
57
+ styles/
58
+ content.css # Styles injected alongside content scripts
59
+
60
+ popup/
61
+ index.html # Popup page HTML (references compiled JS)
62
+ index.ts # Popup entry point
63
+ App.tsx # Root component (if using React)
64
+ components/
65
+ Toggle.tsx
66
+ StatusBadge.tsx
67
+ hooks/
68
+ useExtensionState.ts
69
+
70
+ options/
71
+ index.html # Options page HTML
72
+ index.ts # Options page entry point
73
+ App.tsx
74
+ components/
75
+ SettingsForm.tsx
76
+ PermissionsPanel.tsx
77
+
78
+ shared/
79
+ messages.ts # Message type constants (used by all contexts)
80
+ storage.ts # chrome.storage typed wrappers and key constants
81
+ types.ts # Shared TypeScript interfaces
82
+ constants.ts # App-wide constants (version, default config)
83
+ utils/
84
+ url-helpers.ts
85
+ sanitizer.ts
86
+ ```
87
+
88
+ **Why isolate by context:**
89
+ - Content scripts run in the page context with restricted API access (no `chrome.tabs`, for example).
90
+ - Service workers have no DOM access and are terminated between events.
91
+ - Popup and options pages are full HTML pages with full API access but a different lifecycle from the service worker.
92
+ - Keeping code per context prevents accidental API calls that are undefined in that context and makes the build configuration's entry points map directly to directories.
93
+
94
+ ### public/ — Static Assets
95
+
96
+ ```
97
+ public/
98
+ icons/
99
+ icon-16.png # 16×16 toolbar icon
100
+ icon-32.png # 32×32 (Windows HiDPI toolbar)
101
+ icon-48.png # 48×48 (extension management page)
102
+ icon-128.png # 128×128 (Chrome Web Store listing)
103
+ images/
104
+ logo.svg # Brand assets for options page
105
+ ```
106
+
107
+ **Icon requirements:**
108
+ - Provide all four sizes (16, 32, 48, 128). Missing sizes cause the browser to scale up smaller icons, producing blurry results.
109
+ - Icons must be PNG. SVG is not supported in `manifest.json` icon fields.
110
+ - Design icons to be recognizable at 16×16 (the smallest size shown in the toolbar). Detailed illustrations fail at this scale.
111
+ - Provide separate icon sets for active and inactive states if the extension toggles on/off — users expect visual feedback.
112
+ - The Chrome Web Store also requires a 440×280 promotional tile and up to 5 screenshots. These belong in a separate `store-assets/` directory at the repo root, not in `public/`.
113
+
114
+ ### _locales/ — Internationalization
115
+
116
+ ```
117
+ _locales/
118
+ en/
119
+ messages.json # English strings (required, used as fallback)
120
+ es/
121
+ messages.json
122
+ fr/
123
+ messages.json
124
+ ja/
125
+ messages.json
126
+ ```
127
+
128
+ The `_locales/` directory must be copied verbatim to `dist/` by the build tool. It is not processed — the WebExtensions runtime reads it directly. Configure your bundler to copy `_locales/` as a static asset.
129
+
130
+ ### dist/ — Build Output
131
+
132
+ ```
133
+ dist/
134
+ manifest.json # Copied from root, possibly with env substitutions
135
+ background.js # Compiled service worker bundle
136
+ content.js # Compiled content script bundle
137
+ content.css # Compiled content script stylesheet
138
+ popup/
139
+ index.html
140
+ popup.js
141
+ popup.css
142
+ options/
143
+ index.html
144
+ options.js
145
+ options.css
146
+ icons/ # Copied from public/icons/
147
+ _locales/ # Copied from source _locales/
148
+ ```
149
+
150
+ The directory structure in `dist/` must match what `manifest.json` references in its `background.service_worker`, `content_scripts`, and `action.default_popup` fields. Mismatches cause silent failures — the extension loads but the referenced scripts do not execute.
151
+
152
+ ### tests/ Structure
153
+
154
+ ```
155
+ tests/
156
+ unit/
157
+ shared/ # Tests for shared utility functions
158
+ background/ # Unit tests for background handlers
159
+ content/ # Unit tests for content script logic
160
+ integration/
161
+ background.test.ts # Chrome extension API mocked integration tests
162
+ popup.test.ts
163
+ e2e/
164
+ extension.spec.ts # Playwright tests with real extension loaded
165
+ ```
166
+
167
+ Test files mirror the source structure. Unit tests for `src/shared/storage.ts` live in `tests/unit/shared/storage.test.ts`. Integration and e2e tests live at their own level because they span multiple contexts.
168
+
169
+ ### Configuration Files at Root
170
+
171
+ Keep build and tooling configuration files at the root, not inside `src/`:
172
+
173
+ ```
174
+ vite.config.ts # Multi-entry Vite build config
175
+ tsconfig.json # Base TypeScript config
176
+ tsconfig.content.json # Context-specific tsconfig for content scripts (lib: DOM)
177
+ tsconfig.background.json # Context-specific tsconfig (lib: WebWorker)
178
+ .eslintrc.json
179
+ .prettierrc
180
+ web-ext-config.yml # web-ext tool configuration for dev/testing
181
+ ```
182
+
183
+ Context-specific `tsconfig` files are important: the service worker uses the `WebWorker` lib (not `DOM`), while content scripts and popup use the `DOM` lib. A single tsconfig targeting both will produce incorrect type checking.
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: browser-extension-requirements
3
+ description: User permissions model, store policies (Chrome Web Store, AMO), accessibility requirements, and performance budgets for browser extensions
4
+ topics: [browser-extension, requirements, permissions, store-policies, accessibility, performance]
5
+ ---
6
+
7
+ Browser extension requirements differ fundamentally from web app requirements because the extension operates inside a user's browser with elevated trust and broad access to browsing data. Every permission requested must be justified, every store policy must be understood before writing code, and performance budgets must be set early because extensions run on every page a user visits — regressions directly degrade the entire browsing experience.
8
+
9
+ ## Summary
10
+
11
+ Browser extension requirements center on four domains: permissions (request only what the feature requires, justify each in the store listing), store policies (Chrome Web Store and AMO have distinct review timelines and policy sets that affect architecture decisions), accessibility (popup UIs must meet WCAG 2.1 AA, keyboard-only operation is mandatory), and performance budgets (content scripts add parse time to every page load, service workers must stay under memory limits). Lock these down before implementation to avoid costly store rejections or permission refactors.
12
+
13
+ ## Deep Guidance
14
+
15
+ ### User Permissions Model
16
+
17
+ The permissions model is the most consequential requirement decision. Every permission granted to an extension represents a promise to the user and a liability in the store review process.
18
+
19
+ **Permission categories in Manifest V3:**
20
+
21
+ - `permissions` — Declared API access that is always active (e.g., `storage`, `tabs`, `alarms`, `contextMenus`). Granted at install time with no per-use prompt.
22
+ - `host_permissions` — Access to specific origins or all origins (`<all_urls>`). Triggers a prominent install-time warning. In MV3, these can be made optional via `optional_host_permissions`.
23
+ - `optional_permissions` — APIs requested at runtime via `chrome.permissions.request()`. Prefer optional for features that not all users need.
24
+
25
+ **Principle of least privilege — apply strictly:**
26
+
27
+ - Never request `<all_urls>` if you only need `https://api.example.com/*`. Broad host permissions trigger stricter review and user concern.
28
+ - Request `tabs` only if you need tab URL, title, or favicon. If you only need the active tab's content, use `activeTab` instead — it requires no persistent permission and is granted only on explicit user gesture.
29
+ - Audit permissions on every sprint. Remove any permission no longer used by shipping features.
30
+
31
+ **Sensitive permissions that trigger enhanced review:**
32
+
33
+ - `webRequest` / `declarativeNetRequest` — Modifying network requests is the highest-scrutiny permission. Justify it explicitly in your store listing.
34
+ - `history` — Access to browsing history requires strong justification.
35
+ - `cookies` — Access to cookies including session tokens requires explicit user-facing documentation of what data is accessed and why.
36
+ - `nativeMessaging` — Communicates with native applications; triggers manual review on CWS.
37
+
38
+ **Communicating permissions to users:**
39
+
40
+ - Write a clear Privacy Policy linked in the store listing before submission. Extensions that access user data without a privacy policy are rejected.
41
+ - The store listing description must explain every permission in plain language. "This extension requires access to all websites to block ads" is better than silence.
42
+
43
+ ### Chrome Web Store Policies
44
+
45
+ The Chrome Web Store (CWS) review process is automated for most submissions but involves manual review for sensitive permissions or policy violations.
46
+
47
+ **Key policies affecting architecture:**
48
+
49
+ - **Single purpose policy**: An extension must have a single, clearly described purpose. A "productivity suite" that does 10 unrelated things will be rejected. Define the purpose before writing code.
50
+ - **No remote code execution**: Extensions cannot load and execute remote JavaScript. All logic must be bundled at submission time. This directly prohibits `eval()`, `new Function()`, and dynamic `<script>` injection from remote URLs.
51
+ - **Data use transparency**: Any data collected or transmitted must be disclosed in the Privacy Policy and the Data Use section of the developer console.
52
+ - **Deceptive behavior**: Extensions must not alter user settings (search engine, homepage, new tab page) without explicit opt-in. Implementing a new tab override requires a first-run setup flow where the user explicitly enables it.
53
+
54
+ **Review timelines:**
55
+
56
+ - New extensions: 1–3 business days for automated review; manual review can take 1–2 weeks.
57
+ - Updates to existing extensions: typically 24–72 hours.
58
+ - Permission changes in updates trigger re-review and may prompt existing users to re-approve.
59
+
60
+ **CWS rejection common causes:**
61
+
62
+ - Requesting permissions not used by any feature in the submitted version.
63
+ - Missing or incomplete Privacy Policy for extensions that access user data.
64
+ - Violating the remote code execution policy (using `eval` in content scripts).
65
+ - Deceptive store listing (screenshots that do not match actual functionality).
66
+
67
+ ### Mozilla Add-ons (AMO) Policies
68
+
69
+ AMO (addons.mozilla.org) has a more developer-friendly review process but with distinct requirements:
70
+
71
+ - **Source code review**: AMO reviewers may request the unminified source code for manual inspection. Always submit source maps or the raw source alongside minified builds.
72
+ - **No obfuscation**: Obfuscated code is not permitted. Minification is fine; intentional obfuscation is grounds for rejection.
73
+ - **Listed vs. self-distributed**: AMO-listed extensions receive a full review. Self-distributed (signed but unlisted) extensions receive only automated signing. Most extensions should target listed status.
74
+ - **WebExtensions API compliance**: AMO does not support Manifest V3 features that Chrome added post-specification. Use `webextension-polyfill` and test against the current Firefox ESR.
75
+
76
+ ### Accessibility Requirements
77
+
78
+ Extension popup UIs are full web interfaces and must meet WCAG 2.1 AA:
79
+
80
+ - **Keyboard navigation**: Every interactive element must be reachable and operable via keyboard alone. Tab order must be logical. Focus must be visible at all times.
81
+ - **Color contrast**: Text must meet 4.5:1 contrast ratio for normal text, 3:1 for large text. Dark-mode-only extensions are exempt from light-mode contrast checks but must still pass in their target mode.
82
+ - **ARIA roles**: Use semantic HTML first. Add ARIA roles only where semantic HTML is insufficient. Popup UIs are typically small enough that semantic HTML covers all cases.
83
+ - **Screen reader compatibility**: Test with NVDA + Firefox and VoiceOver + Chrome. Extension popups open in a context that screen readers handle differently from regular web pages — verify announce behavior on open.
84
+
85
+ Content scripts that inject UI into host pages must not break the host page's existing accessibility tree. Use `aria-hidden` on injected containers where appropriate and avoid stealing focus unexpectedly.
86
+
87
+ ### Performance Budgets
88
+
89
+ Extensions impose a cost on every page load and every browser session. Set explicit budgets before implementation:
90
+
91
+ **Content script budgets:**
92
+ - Parse + execute time: under 50 ms on a mid-range device for the combined content script bundle.
93
+ - DOM manipulation: defer DOM modifications until `DOMContentLoaded` or later. Synchronous DOM work in `document_start` blocks page render.
94
+ - Bundle size: content script bundle under 100 KB (uncompressed). Prefer tree-shaken, purpose-built code over importing full utility libraries.
95
+
96
+ **Service worker budgets:**
97
+ - Background service workers are terminated after ~30 seconds of inactivity in Chrome. Design for stateless, event-driven operation.
98
+ - Memory ceiling: Chrome enforces a per-extension memory limit. Keep the service worker footprint under 50 MB. Use `chrome.storage` for persistent state rather than in-memory caches.
99
+
100
+ **Popup UI budgets:**
101
+ - Popup open-to-interactive: under 300 ms. Popups that block on slow network requests before rendering anything will feel broken.
102
+ - Bundle size: popup bundle under 200 KB. Users open and close popups frequently; fast load matters.
103
+
104
+ **Measurement:**
105
+ - Profile content scripts with Chrome DevTools Performance panel on a cold-cache page load.
106
+ - Use `chrome.runtime.getBackgroundPage()` (MV2) or service worker `self.performance` metrics to measure background processing time.
107
+ - Run Lighthouse on the popup HTML file directly to catch performance regressions in the UI.