Skip to content

doc(policies): add security, privacy, accessibility and support documents - #2383

Open
rkaraivanov wants to merge 7 commits into
masterfrom
docs/security-compliance-privacy
Open

rkaraivanov wants to merge 7 commits into
masterfrom
docs/security-compliance-privacy

Conversation

@rkaraivanov

Copy link
Copy Markdown
Member

Rewrite SECURITY.md around the agreed support window: all fixes for the
latest major, critical fixes backported to the last minor of the previous
major. Add scope, response targets, disclosure, release verification with
gh attestation, and security considerations for consumers (chat sanitizer,
icon and QR URL fetches, clipboard, CSP).

Add PRIVACY.md stating the no-telemetry, no-storage, no-remote-code
position and listing the browser capabilities the components touch.

Add ACCESSIBILITY.md with the WCAG 2.1 AA target, how axe audits and
manual NVDA checks verify it, and how the components work around ARIA
relations that cannot cross shadow boundaries with ElementInternals and
ARIA element reflection.

Add SUPPORT.md and an issue-template config that routes security reports
to private vulnerability reporting.

Add scripts/build-notices.mjs, which reads the runtime and optional peer
dependencies from the published manifest, collects each package's license
text from node_modules, and writes THIRD-PARTY-NOTICES.md. lit and
@lit/context are BSD-3-Clause, which requires notice reproduction.

Updated README, CONTRIBUTING and issue/PR templates.

…ents

Rewrite SECURITY.md around the agreed support window: all fixes for the
latest major, critical fixes backported to the last minor of the previous
major. Add scope, response targets, disclosure, release verification with
gh attestation, and security considerations for consumers (chat sanitizer,
icon and QR URL fetches, clipboard, CSP).

Add PRIVACY.md stating the no-telemetry, no-storage, no-remote-code
position and listing the browser capabilities the components touch.

Add ACCESSIBILITY.md with the WCAG 2.1 AA target, how axe audits and
manual NVDA checks verify it, and how the components work around ARIA
relations that cannot cross shadow boundaries with ElementInternals and
ARIA element reflection.

Add SUPPORT.md and an issue-template config that routes security reports
to private vulnerability reporting.
Add scripts/build-notices.mjs, which reads the runtime and optional peer
dependencies from the published manifest, collects each package's license
text from node_modules, and writes THIRD-PARTY-NOTICES.md. lit and
@lit/context are BSD-3-Clause, which requires notice reproduction.

The file records declared version ranges rather than installed versions,
so `check-notices` (picked up by `npm run check`) fails only when a
dependency is added, removed or relicensed, not on patch bumps.
`build:publish` regenerates the file and copies it into dist next to
LICENSE.
CodeQL analyzes the TypeScript sources on push, pull request and weekly,
skipping build output and spec/story files. Scorecard runs on push to
master, on branch-protection changes and weekly, publishing results so
the README badge and API resolve; the job follows the publishing API's
workflow restrictions.

Pin every action in the CI and Storybook workflows to a commit SHA with
the version in a trailing comment, matching the release workflow.
Dependabot keeps the pins current.
Move the lint, check, test and Storybook commands from the README into
CONTRIBUTING. Add sections on accessibility requirements (axe on both DOM
trees, APG keyboard patterns, ElementInternals over IDREF), dependency
policy (discuss first, permissive licenses only, both manifests, notices
regeneration, SHA-pinned actions), security expectations for changes, and
the Keep a Changelog `Security` category. State that no CLA or DCO
sign-off is required.

Extend the pull request checklist with changelog, accessibility,
dependency and security items.
Reorder into quick start, components, browser support, tooling, then
short Accessibility, Security and supply chain, Privacy, Contributing,
Support and License sections that each link to their document. Add
CodeQL, OpenSSF Scorecard and license badges and a table of contents.

Development commands now live in CONTRIBUTING. New document links are
absolute URLs because the same README ships in the npm package.
@rkaraivanov
rkaraivanov requested review from damyanpetev and a lite review from Copilot September 16, 2026 10:44
@rkaraivanov rkaraivanov added documentation Improvements or additions to documentation squash-merge Build/CI labels Sep 16, 2026
GitHub rejects SARIF from a workflow-based CodeQL configuration while
default setup is enabled for the repository, and default setup already
scans javascript-typescript on every push and pull request. Remove the
workflow and its README badge, and describe the default setup in the
README and SECURITY.md.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical workflow and moderate license-notice issues remain, along with documentation and contribution-policy corrections.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This PR adds security, privacy, accessibility, support, and supply-chain documentation, plus license-notice automation and security workflows.

Changes:

  • Adds policy documents, support routing, and updated contributor templates.
  • Generates and packages third-party license notices.
  • Adds CodeQL/Scorecard workflows and pins CI actions.
File summaries
File Summary and final findings
THIRD-PARTY-NOTICES.md Generated dependency notices. Moderate (1 vote): marked-shiki lacks reproduced MIT license text; add a vetted fallback or fail generation.
SECURITY.md Security policy and release guidance. Nit (1 vote): Document both immediate logo-src loading and later export fetching.
scripts/build.mjs Packages third-party notices.
scripts/build-notices.mjs Notice generation. Moderate (2 votes): Respect peerDependenciesMeta when labeling optional peers. Moderate (1 vote): Handle missing license files with a reviewed fallback or failure. Nit (1 vote): Replace unchecked any types with validated unknown shapes.
README.md Adds policy and security links. Nit (3 votes): Correct the universal claim that every specification audits both DOM trees.
PRIVACY.md Privacy commitments and browser capabilities. Nit (3 votes): Qualify host-supplied URL fetches. Nit (2 votes): Document BroadcastChannel usage and distinguish automatic capabilities. Nit (1 vote): Clarify automatic locale/time-zone and reduced-motion checks. Nit (1 vote): Correct the reduced-motion media query. Nit (1 vote): Document both logo-src and export-time image requests.
package.json Adds notice build and check scripts.
ACCESSIBILITY.md Accessibility targets and verification. Nit (3 votes): Qualify or complete light/shadow DOM audit coverage. Nit (1 vote): Document the same-root aria-describedby exception.
.github/workflows/scorecard.yml Adds Scorecard analysis. Critical (2 votes): Add contents: read so checkout can access the repository.
.github/workflows/node.js.yml Pins CI actions.
.github/workflows/gh-pages-deploy.yml Pins deployment actions.
.github/workflows/codeql.yml Adds CodeQL analysis.
.github/SUPPORT.md Adds support routing.
.github/pull_request_template.md Adds review checklists.
.github/ISSUE_TEMPLATE/config.yml Routes security reports privately.
.github/CONTRIBUTING.md Expands contribution requirements. Nit (1 vote): Align the mandatory light-DOM audit rule with existing specifications. Nit (1 vote): Add the required [Unreleased] changelog entry.
Review details

Suppressed comments (11)

.github/CONTRIBUTING.md:100

  • This new mandatory rule is not compatible with existing specifications: src/components/qr-code/qr-code.spec.ts:18-22 and src/components/navbar/navbar.spec.ts:10-16 have no light-DOM audit. Update the affected specs in the same change or scope the requirement to cases where a light-DOM audit is applicable.
- Every component specification must audit the component with axe, on both its light DOM and its shadow DOM, in each state the specification exercises: `await expect(el).to.be.accessible()` and `await expect(el).shadowDom.to.be.accessible()`.

.github/CONTRIBUTING.md:94

  • This PR adds user-visible policy and contributor documentation but does not add an entry under the existing [Unreleased] section in CHANGELOG.md. That conflicts with the changelog requirement being introduced here; add a concise Added or Changed entry before merge.
- **Changelog**: Add an entry under `[Unreleased]` in [CHANGELOG.md](../CHANGELOG.md) for every user-visible change. The file follows [Keep a Changelog](https://keepachangelog.com/), so use the `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed` and `Security` categories. A fix for a vulnerability goes under `Security`, with a link to the advisory once it is published.

ACCESSIBILITY.md:36

  • This says all relations use element references, but the implementation intentionally keeps the editor's own description as a same-root aria-describedby IDREF when no projected description exists (see src/internals/controllers/aria-projection.ts:64-68 and 198-200). Qualify this to cross-root relations and document the same-root exception.
- **ARIA element reflection.** Relations are set as element references (`ariaLabelledByElements`, `ariaDescribedByElements`, `ariaControlsElements`, `ariaActiveDescendantElement`) rather than IDREF strings. Element reflection resolves across shadow boundaries into ancestor tree scopes, which lets a composite component point at an element the page or another component owns. The projection controller in `src/internals/controllers/aria-projection.ts` carries those references to the native control inside an input-shaped component, since that is the element assistive technology lands on.

PRIVACY.md:24

  • This sentence overstates the boundary: the icon registry deliberately publishes user-registered icon SVGs and references over BroadcastChannel to same-origin browsing contexts, and the fetch rows send host-supplied URLs to their origins. Qualify it to data rendered by the components except for the explicitly documented network and cross-context operations.
Data your application passes into a component, such as chat messages, form values or dates, stays in the page. The components render it and expose it back through their properties and events, and nowhere else.

PRIVACY.md:14

  • Locale/time-zone formatting and reduced-motion checks are performed automatically while components render or animate; they are not all triggered by an explicit host call or user action. Narrow this sentence to the network and clipboard operations, or state that these preferences may be read automatically.
Some components use browser APIs that can involve user data. Each is triggered only by an explicit call from the host application or by a user action inside the component.

PRIVACY.md:22

  • The documented media query does not match the implementation, which calls matchMedia('(prefers-reduced-motion: reduce)'). Correcting the query is important for consumers who use this table to audit browser capabilities.
| Reduced-motion preference     | Animations                           | Read through `matchMedia('(prefers-reduced-motion)')` to shorten or skip animations.           |

PRIVACY.md:19

  • Assigning logo-src already creates an Image and loads the URL to determine its dimensions; exporting then may fetch the same non-data URL again to inline it. Describing the request as occurring only during QR export can cause consumers to miss a network/privacy request at render time.
| `fetch` of an application URL | QR code export with an embedded image| Only for the image URL the host application passes to the export call.                         |

SECURITY.md:79

  • Setting logo-src loads the image immediately to determine its aspect ratio, before any export call; toBlob()/toImage() can then fetch it again while inlining it. Document both triggers so consumers do not assume this request is deferred until export.
- **QR code export.** Exporting a QR code with an embedded image fetches the image URL you pass to draw it on a canvas. Only supply URLs you trust.

THIRD-PARTY-NOTICES.md:836

  • This generated section is the only entry without reproduced license text: it lists MIT for marked-shiki but emits only a pointer to its repository. That does not meet the document's stated goal of carrying license terms for redistributors and contradicts the PR description's promise to collect each package's license text. Please add a vetted license-text fallback or fail notice generation when a declared license file is absent.
The package ships no license file. Its manifest declares `MIT`; refer to the source repository for the license text.

scripts/build-notices.mjs:110

  • When a package has no matching file, this path records only the SPDX identifier and emits no license text. The generated notice currently does this for marked-shiki, even though the document promises license terms and the package declares MIT; an identifier plus a repository link does not reproduce the MIT grant/attribution. Please fail generation or provide a reviewed fallback/override for packages that omit their license file instead of silently accepting an incomplete notice.
  if (files.length === 0) {
    log(CATEGORY, `${name} ships no license file; recording its SPDX id only`);
  }

scripts/build-notices.mjs:19

  • The new script uses any for parsed JSON and manifests in four JSDoc signatures. This bypasses the repository's strict typing guidance and makes malformed manifest shapes unchecked; define a manifest/notice input shape and use unknown plus validation/narrowing instead.
/**
 * @param {string} file - Path to a JSON file.
 * @returns {any} Parsed content.
 */
  • Files reviewed: 15/15 changed files
  • Comments generated: 6
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/scorecard.yml
Comment thread scripts/build-notices.mjs
Comment thread ACCESSIBILITY.md Outdated
Comment thread PRIVACY.md Outdated
Comment thread PRIVACY.md Outdated
Comment thread README.md Outdated
Correct claims that did not match the source: only some specifications
audit both the light and the shadow DOM, the reduced-motion query is
"(prefers-reduced-motion: reduce)", a QR logo loads when logo-src is set
and again on export, and the icon registry opens a same-origin
BroadcastChannel automatically. Qualify the "no third party" and
"nowhere else" statements in PRIVACY.md to the documented host-supplied
URL fetches, and note the same-root aria-describedby exception in
ACCESSIBILITY.md.

Make the notices generator label peers from peerDependenciesMeta instead
of assuming every peer is optional, and fail when a package declares a
license but ships no license file unless a reviewed copy exists under
scripts/license-overrides. Add the MIT text for marked-shiki from its
source repository and record the shipped notices file in the changelog.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Build/CI documentation Improvements or additions to documentation squash-merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants