diff --git a/.changeset/config.json b/.changeset/config.json
index 3bcb600..26ffa0c 100644
--- a/.changeset/config.json
+++ b/.changeset/config.json
@@ -1,9 +1,6 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
- "changelog": [
- "@changesets/changelog-github",
- { "repo": "level0x40/virtual-frame" }
- ],
+ "changelog": ["@changesets/changelog-github", { "repo": "level0x40/virtual-frame" }],
"commit": false,
"fixed": [],
"linked": [],
diff --git a/.changeset/lazy-terms-invent.md b/.changeset/lazy-terms-invent.md
new file mode 100644
index 0000000..5acc216
--- /dev/null
+++ b/.changeset/lazy-terms-invent.md
@@ -0,0 +1,19 @@
+---
+"@virtual-frame/analog": patch
+"@virtual-frame/angular": patch
+"virtual-frame": patch
+"@virtual-frame/next": patch
+"@virtual-frame/nuxt": patch
+"@virtual-frame/react": patch
+"@virtual-frame/react-router": patch
+"@virtual-frame/react-server": patch
+"@virtual-frame/solid": patch
+"@virtual-frame/solid-start": patch
+"@virtual-frame/store": patch
+"@virtual-frame/svelte": patch
+"@virtual-frame/sveltekit": patch
+"@virtual-frame/tanstack-start": patch
+"@virtual-frame/vue": patch
+---
+
+Initial publish
diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml
index ad54d5b..757081a 100644
--- a/.github/actions/setup/action.yml
+++ b/.github/actions/setup/action.yml
@@ -1,5 +1,5 @@
name: Setup
-description: Install pnpm, set up Node.js with pnpm cache, and install dependencies (frozen lockfile).
+description: Install Vite+ (vp), set up Node.js with dependency caching, and install dependencies (frozen lockfile).
inputs:
node-version:
@@ -10,15 +10,12 @@ inputs:
runs:
using: composite
steps:
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
-
- - name: Setup Node.js
- uses: actions/setup-node@v4
+ - name: Setup Vite+
+ uses: voidzero-dev/setup-vp@v1
with:
node-version: ${{ inputs.node-version }}
- cache: pnpm
+ cache: true
- name: Install dependencies
shell: bash
- run: pnpm install --frozen-lockfile
+ run: vp install --frozen-lockfile
diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml
new file mode 100644
index 0000000..761c2d4
--- /dev/null
+++ b/.github/codeql/codeql-config.yml
@@ -0,0 +1,34 @@
+name: "virtual-frame CodeQL config"
+
+# Preserve the query suite configured in the workflow — this file only
+# narrows what gets reported, it does not choose the suite.
+
+query-filters:
+ # Polynomial-regex detector flags any regex with an unbounded repetition
+ # that is evaluated against library input. Across virtual-frame's
+ # HTML-parsing regexes (e.g. `/]*>/gi`) the pattern is always a
+ # single non-overlapping quantifier anchored by a literal — linear in
+ # input length with no ReDoS path. The rule's own description says it
+ # "*may* run slow" because it cannot prove otherwise; we have proved
+ # otherwise by construction. Suppressed globally.
+ - exclude:
+ id: js/polynomial-redos
+
+paths-ignore:
+ # Dedicated security boundary. virtual-frame is a "virtual iframe" —
+ # its entire purpose is to embed HTML fetched from a caller-chosen
+ # remote origin (see SECURITY.md, "Security model for embedded
+ # content"). This file contains the narrow set of intentional HTML
+ # sinks; reviewing it by hand is the security model, so CodeQL's
+ # html-injection queries are deliberately excluded here. The rest of
+ # the workspace stays under full analysis — any html-injection pattern
+ # introduced outside this file is a real finding.
+ - "packages/**/src/internal/html-sink.ts"
+
+ # Tests and fixtures. Noise from fixture data outweighs signal.
+ - "**/*.test.ts"
+ - "**/*.test.tsx"
+ - "**/test/**"
+ - "**/__tests__/**"
+ - "e2e/**"
+ - "examples/**"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 61bc4fd..b97003d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,7 +29,7 @@ jobs:
pull-requests: read
steps:
- name: Validate Conventional Commits format
- uses: amannn/action-semantic-pull-request@v5
+ uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
@@ -57,72 +57,107 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: ./.github/actions/setup
- name: Check formatting
- run: pnpm format:check
+ run: vp run format:check
- name: Lint
- run: pnpm lint
+ run: vp run lint
# ──────────────────────────────────────────────────────────────────────
- # Type-check across the workspace. Today this is a real CI gap.
+ # Build all packages and examples. Uploads dist/ artifacts for
+ # downstream jobs (typecheck, test, e2e) so they don't rebuild.
+ # ──────────────────────────────────────────────────────────────────────
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+ steps:
+ - uses: actions/checkout@v5
+ - uses: ./.github/actions/setup
+
+ - name: Build all packages
+ run: vp run build
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v5
+ with:
+ name: build-output
+ path: |
+ packages/*/dist
+ retention-days: 1
+
+ - name: Upload generated route files
+ uses: actions/upload-artifact@v5
+ with:
+ name: generated-routes
+ path: |
+ examples/*/src/routeTree.gen.ts
+ retention-days: 1
+
+ # ──────────────────────────────────────────────────────────────────────
+ # Type-check across the workspace.
# ──────────────────────────────────────────────────────────────────────
typecheck:
name: Typecheck
+ needs: [build]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: ./.github/actions/setup
+ - name: Download build artifacts
+ uses: actions/download-artifact@v5
+ with:
+ name: build-output
+ path: packages
+
+ - name: Download generated route files
+ uses: actions/download-artifact@v5
+ with:
+ name: generated-routes
+ path: examples
+
- name: Typecheck all packages
- run: pnpm typecheck
+ run: vp run typecheck
# ──────────────────────────────────────────────────────────────────────
# Unit + browser tests via vitest.
# ──────────────────────────────────────────────────────────────────────
test:
name: Unit Tests
+ needs: [build]
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: ./.github/actions/setup
+ - name: Download build artifacts
+ uses: actions/download-artifact@v5
+ with:
+ name: build-output
+ path: packages
+
- name: Install Playwright browsers
# vitest browser mode uses Playwright's chromium under the hood.
- run: pnpm exec playwright install --with-deps chromium
+ run: npx playwright install --with-deps chromium
- name: Run vitest
- run: pnpm test:run
+ run: vp run test:run
- name: Upload coverage
if: always()
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v5
with:
name: coverage
path: coverage/
if-no-files-found: ignore
retention-days: 14
- # ──────────────────────────────────────────────────────────────────────
- # Build all packages. Produces dist/ artifacts that e2e relies on
- # implicitly (e2e prod-mode builds each example, which transitively
- # consumes built packages).
- # ──────────────────────────────────────────────────────────────────────
- build:
- name: Build
- runs-on: ubuntu-latest
- timeout-minutes: 20
- steps:
- - uses: actions/checkout@v4
- - uses: ./.github/actions/setup
-
- - name: Build all packages
- run: pnpm build
-
# ──────────────────────────────────────────────────────────────────────
# End-to-end Playwright suite — boots real example apps in dev and prod
# mode against a real browser. This is a required gate.
@@ -133,19 +168,27 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: ./.github/actions/setup
+ - name: Download build artifacts
+ uses: actions/download-artifact@v5
+ with:
+ name: build-output
+ path: packages
+
- name: Install Playwright browsers
working-directory: e2e
- run: pnpm exec playwright install --with-deps chromium
+ run: npx playwright install --with-deps chromium
- name: Run E2E suite
- run: pnpm test:e2e
+ run: vp run test:e2e
+ env:
+ VF_E2E_VERBOSE: "1"
- name: Upload Playwright report
if: failure()
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v5
with:
name: playwright-report
path: |
@@ -166,14 +209,14 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
# changeset status needs main as a comparison base.
fetch-depth: 0
- uses: ./.github/actions/setup
- name: Verify changeset present
- run: pnpm changeset status --since=origin/${{ github.base_ref }}
+ run: vp run changeset status --since=origin/${{ github.base_ref }}
# ──────────────────────────────────────────────────────────────────────
# Aggregate gate — single status for branch protection to require.
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index cd81fe2..1015cd7 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -51,6 +51,10 @@ jobs:
# queries; security-extended is a good balance for a runtime
# library.
queries: security-extended
+ # Path filters and per-rule suppressions live in a separate
+ # config file so the rationale is version-controlled alongside
+ # the exclusions.
+ config-file: ./.github/codeql/codeql-config.yml
- name: Autobuild
# JS/TS does not require a build step for analysis; autobuild is
diff --git a/.gitignore b/.gitignore
index 8cc1a34..66f501a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,11 +9,14 @@ packages/*/LICENSE
**/.next
**/.nuxt
**/.output
+**/.react-router
**/.react-server
**/.svelte-kit
**/build
+**/@mf-types
.viteplus
*.local
.DS_Store
*.tsbuildinfo
-**/__screenshots__
\ No newline at end of file
+**/__screenshots__
+**/routeTree.gen.ts
\ No newline at end of file
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 67f9def..1cddbb2 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -1,4 +1,3 @@
-
# Contributor Covenant Code of Conduct
## Our Pledge
@@ -11,19 +10,19 @@ We pledge to act and interact in ways that contribute to an open, welcoming, div
Examples of behavior that contributes to a positive environment for our community include:
-* Demonstrating empathy and kindness toward other people
-* Being respectful of differing opinions, viewpoints, and experiences
-* Giving and gracefully accepting constructive feedback
-* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
-* Focusing on what is best not just for us as individuals, but for the overall community
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
+- Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
-* The use of sexualized language or imagery, and sexual attention or advances of any kind
-* Trolling, insulting or derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or email address, without their explicit permission
-* Other conduct which could reasonably be considered inappropriate in a professional setting
+- The use of sexualized language or imagery, and sexual attention or advances of any kind
+- Trolling, insulting or derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or email address, without their explicit permission
+- Other conduct which could reasonably be considered inappropriate in a professional setting
## Enforcement Responsibilities
@@ -82,4 +81,3 @@ For answers to common questions about this code of conduct, see the FAQ at [http
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
-
diff --git a/README.md b/README.md
index 060ac00..73fb11d 100644
--- a/README.md
+++ b/README.md
@@ -102,10 +102,7 @@ npm install virtual-frame
import "virtual-frame/element";
-
+
```
### React
diff --git a/SECURITY.md b/SECURITY.md
index ff5d943..4ea971f 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -6,10 +6,10 @@ We take the security of Virtual Frame seriously. This document explains how to r
Security fixes land on the latest minor release line of each package. We do not back-port to older minors.
-| Package family | Supported |
-| ---------------------------- | ---------------------------------- |
-| `virtual-frame` (core) | Latest minor |
-| `@virtual-frame/*` bindings | Latest minor |
+| Package family | Supported |
+| ---------------------------------------------------------- | ------------ |
+| `virtual-frame` (core) | Latest minor |
+| `@virtual-frame/*` bindings | Latest minor |
| `@virtual-frame/*` integrations (Next/Nuxt/SvelteKit/etc.) | Latest minor |
While the project remains pre-1.0 (`0.x`), every `0.x` minor bump may include breaking changes; security fixes target the most recent published minor only.
@@ -39,11 +39,11 @@ If you'd like to encrypt your report, request our PGP key in the first message.
### What to expect
-| Timeframe | What we do |
-| ------------------ | -------------------------------------------------------------------------- |
+| Timeframe | What we do |
+| ----------------------- | -------------------------------------------------------------------------- |
| Within 3 business days | Initial acknowledgement — we've received your report and are assessing it. |
| Within 10 business days | Triage outcome — confirmed, declined, or duplicate, with reasoning. |
-| Within 90 days | Fix released, advisory published, and credit assigned (if accepted). |
+| Within 90 days | Fix released, advisory published, and credit assigned (if accepted). |
For critical issues actively exploited in the wild, we'll work with you on an accelerated disclosure timeline.
@@ -71,6 +71,24 @@ We support coordinated disclosure. As long as you act in good faith, comply with
- Treat your testing as authorized under the Computer Fraud and Abuse Act and equivalent laws.
- Work with you on disclosure timing.
+## Security model for embedded content
+
+Virtual Frame is, by design, a mechanism for embedding HTML from a remote origin into a server-rendered response — a "virtual iframe". The trust model is the same one you accept when you write `