Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1685,6 +1685,77 @@ jobs:
git tag "$TAG"
git push origin "$TAG"

# ── Sync vastlint-python ────────────────────────────────────────────────────
# After a successful release, bump the version in the vastlint-python repo and
# tag it at the same version. The vastlint-python publish workflow then runs
# fetch-libs.sh against this release to vendor the shared libraries and pushes
# the wheel to PyPI via trusted publishing.
#
# Prerequisites (one-time setup):
# 1. Generate an SSH deploy key for vastlint-python:
# ssh-keygen -t ed25519 -f ~/VASTLINT_PYTHON_DEPLOY_KEY -C "vastlint release bot (python)" -N ""
# 2. Add ~/VASTLINT_PYTHON_DEPLOY_KEY.pub as a deploy key in vastlint-python
# (Settings → Deploy keys) with write access.
# 3. Add ~/VASTLINT_PYTHON_DEPLOY_KEY (private key) as secret
# VASTLINT_PYTHON_DEPLOY_KEY in this repo (Settings → Secrets → Actions).
#
# Set ENABLE_PYTHON_SYNC to "true" in repo variables to activate this job.
sync-python:
name: Sync vastlint-python
needs: [release]
runs-on: ubuntu-latest
if: vars.ENABLE_PYTHON_SYNC == 'true'

steps:
- name: Checkout vastlint-python via deploy key
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
repository: aleksUIX/vastlint-python
ssh-key: ${{ secrets.VASTLINT_PYTHON_DEPLOY_KEY }}
path: vastlint-python

- name: Bump version
run: |
TAG="${{ github.ref_name }}"
VERSION="${TAG#v}"
cd vastlint-python
printf '__version__ = "%s"\n' "$VERSION" > src/vastlint/_version.py
echo "set __version__ = ${VERSION}"

- name: Import bot GPG key
run: |
echo "${{ secrets.BOT_GPG_KEY }}" | gpg --batch --import
# Trust the key fully so git can use it without prompts
echo "AEA67F4C8B714AC26E14ACDB67DF23E270B033DB:6:" | gpg --import-ownertrust

- name: Commit and push
run: |
TAG="${{ github.ref_name }}"
cd vastlint-python
git config user.name "vastlint release bot"
git config user.email "bot@vastlint.org"
git config user.signingkey "67DF23E270B033DB"
git config commit.gpgsign true

git add src/vastlint/_version.py
if git diff --cached --quiet; then
echo "version already at ${TAG#v} — nothing to commit"
else
git commit -S -m "chore: release ${TAG}"
git push origin main
fi

- name: Tag vastlint-python
run: |
TAG="${{ github.ref_name }}"
cd vastlint-python
# Fail loudly if the tag already exists — never silently overwrite.
if git ls-remote --tags origin "$TAG" | grep -q "$TAG"; then
echo "::warning::Tag $TAG already exists on vastlint-python — skipping tag push" && exit 0
fi
git tag "$TAG"
git push origin "$TAG"

# ── Chrome Web Store ────────────────────────────────────────────────────────
chrome-extension:
name: Publish Chrome extension
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ GitHub Releases: <https://github.com/aleksUIX/vastlint/releases>

---

## [0.5.0] - 2026-06-13

### Core validator

- **VMAP 1.0 validation**: `validate()` now recognises `<vmap:VMAP>` documents and runs a dedicated 24-rule VMAP chain — `<AdBreak>` structure, `timeOffset`/`breakType`/`repeatAfter` formats, `<AdSource>` content constraints (exactly one of `VASTAdData`/`AdTagURI`/`CustomAdData`, CDATA requirements), VMAP tracking events, and `repeatAfter`/`timeOffset` conflict detection. Inline VAST inside `<vmap:VASTAdData>` is validated with the full VAST rule chain; issues surface with `/VMAP/AdBreak[i]/AdSource/VASTAdData`-prefixed paths and document-absolute line/col.
- **DAAST 1.0 validation**: `<DAAST>` documents run a dedicated 29-rule chain covering the audio-specific deltas from VAST 3.0 — required `<Category>`, optional `<AdSystem>`, `<DAASTAdTagURI>` wrappers, `<AdInteractions>` (with detection of VAST leftovers like `<VideoClicks>` and `<VASTAdTagURI>`), audio MediaFile attributes, the DAAST tracking event set, DAAST pricing models (incl. `cpo`), root-level `<Error>` URI presence, and `[ERRORCODE]` macro inclusion.
- **`ValidationResult.document_type`**: new `DocumentType` enum (`Vast` / `Vmap` / `Daast`) reporting which rule chain ran. `version` stays VAST-specific and is `Unknown` for VMAP/DAAST documents. New `RuleSource` variants: `VmapSpec`, `DaastSpec`, `DaastXsd`. Breaking change: callers that destructure `ValidationResult` must add the new field.
- **Rule catalog grown to 182** (`all_rules()`, RULES.md, VS Code rule list).

### Documentation / metadata

- **RULES.md and VS Code README updated**: all 182 rules listed with correct severities and spec references.
- **README.md rule count updated**: three occurrences of "129 rules" updated to "182 rules"; VMAP 1.0 and DAAST 1.0 added to category list.
- **vastlint.org rule pages**: 53 new per-rule doc pages for all VMAP and DAAST rule IDs, with category impact descriptions, spec links, and XML examples.

### Release metadata

- **Semver bump to 0.5.0**: breaking change due to new public `document_type` field on `ValidationResult`.

## [0.4.24] - 2026-06-09

### Core validator
Expand Down
20 changes: 10 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Validates VAST documents against:
- [IAB Tech Lab SIMID](https://iabtechlab.com/simid/) 1.0, 1.0.1, 1.1, 1.2 — interactive creative validation for `<InteractiveCreativeFile apiFramework="SIMID">` and nonlinear `<IFrameResource>` (the IAB-sanctioned VPAID replacement)
- [IAB Tech Lab OMID / Open Measurement](https://iabtechlab.com/standards/open-measurement-sdk/) compatibility in VAST `<AdVerifications>` — vendor format, duplicate vendor detection, OMID resource semantics, verification tracking validation, and pre-4.1 extension-carried compatibility blocks

129 rules across required fields, schema validation, structural correctness, security, consistency, deprecated features, ambiguous usage, value formats, SIMID validation, and OMID validation. Rules marked with `$` have direct revenue impact - use `vastlint check --fail-on-warning` in CI to catch them before they reach production. See [common errors](docs/common-errors.md) for the ones that cost real money. New to VASTlint? Start with the [tutorial](docs/tutorial.md).
182 rules across required fields, schema validation, structural correctness, security, consistency, deprecated features, ambiguous usage, value formats, SIMID validation, OMID validation, VMAP 1.0, and DAAST 1.0. Rules marked with `$` have direct revenue impact - use `vastlint check --fail-on-warning` in CI to catch them before they reach production. See [common errors](docs/common-errors.md) for the ones that cost real money. New to VASTlint? Start with the [tutorial](docs/tutorial.md).

Full rule reference with examples and fix instructions: [VAST error rule reference](https://vastlint.org/docs/rules) · [RULES.md](RULES.md)

Expand Down Expand Up @@ -379,7 +379,7 @@ All three bindings share the same compiled Rust core — identical rule enforcem

## Use from JavaScript / TypeScript

[`vastlint`](https://www.npmjs.com/package/vastlint) is published on npm. Same 129 rules, same core - compiled to WASM.
[`vastlint`](https://www.npmjs.com/package/vastlint) is published on npm. Same 182 rules, same core - compiled to WASM.

```sh
npm install vastlint
Expand Down Expand Up @@ -517,7 +517,7 @@ Returns the same structured result as the CLI and library: version, issues with

## Use from a browser

Paste any VAST tag into the web validator at **[VAST tag validator](https://vastlint.org/validate)** - no install, no account, nothing stored. Runs the same 129 rules as the CLI, entirely in your browser via WebAssembly.
Paste any VAST tag into the web validator at **[VAST tag validator](https://vastlint.org/validate)** - no install, no account, nothing stored. Runs the same 182 rules as the CLI, entirely in your browser via WebAssembly.

## Telemetry

Expand Down
10 changes: 6 additions & 4 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ Where vastlint is today and where it's going.

| Milestone | Detail |
|---|---|
| **Core library** | `vastlint-core` v0.4 on crates.io - zero-dependency Rust library, 129 rules, VAST 2.0–4.3 plus SIMID and OMID validation. |
| **Core library** | `vastlint-core` v0.5 on crates.io - zero-dependency Rust library, 182 rules, VAST 2.0–4.3 plus SIMID, OMID, VMAP 1.0, and DAAST 1.0 validation. |
| **CLI** | `vastlint` on crates.io and Homebrew (`brew install aleksUIX/tap/vastlint`). JS/WASM on npm, Go bindings on GitHub. |
| **Web validator** | Paste or drop a VAST tag at [vastlint.org/validate](https://vastlint.org/validate) - structured report, nothing stored. |
| **VS Code extension** | Inline VAST XML validation as you type - errors and warnings with rule IDs and spec refs, directly in your editor. [Install →](https://marketplace.visualstudio.com/items?itemName=aleksuix.vastlint) |
| **REST API** | Authenticated `/validate` endpoint on [RapidAPI](https://rapidapi.com/aleksUIX/api/vastlint). Same 129 rules, WASM-powered, sub-millisecond response. |
| **REST API** | Authenticated `/validate` endpoint on [RapidAPI](https://rapidapi.com/aleksUIX/api/vastlint). Same 182 rules, WASM-powered, sub-millisecond response. |
| **VMAP 1.0 validation** | 24 rules covering `<AdBreak>` structure, `timeOffset`/`breakType`/`repeatAfter` formats (including `repeatAfter` + `start`/`end` conflict detection), `<AdSource>` content constraints, VMAP tracking events, and full VAST validation of inline `<vmap:VASTAdData>` ad data. |
| **DAAST 1.0 validation** | 29 rules covering audio-specific VAST 3.0 deltas: required `<Category>`, `<DAASTAdTagURI>` wrappers, `<AdInteractions>` (with VAST-leftover detection), audio MediaFile attributes, DAAST tracking event set, DAAST pricing models, and root-level `<Error>` URI and `[ERRORCODE]` macro checks. |
| **MCP server** | Model Context Protocol server wrapping vastlint-core. Hosted SSE endpoint at `https://vastlint.org/mcp` - no install needed. Six tools: `validate_vast`, `validate_vast_url`, `list_rules`, `explain_rule`, `fix_vast`, `inspect_vast`. Published to [registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io/servers/io.github.aleksUIX/vastlint) and Smithery. Works with Claude Desktop, Cursor, Windsurf, VS Code, and any MCP-compatible client. |
| **AAMP / ARTF compatibility** | vastlint-core and the MCP server are callable by AI buyer and seller agents operating under IAB Tech Lab's [AAMP](https://iabtechlab.com/standards/aamp-agentic-advertising-management-protocols/) and [ARTF](https://iabtechlab.com/standards/artf/) frameworks via the live MCP endpoint. |
| **SIMID validation (all versions)** | `<InteractiveCreativeFile apiFramework="SIMID">` and `<IFrameResource apiFramework="SIMID">` validated against all published SIMID versions (1.0, 1.0.1, 1.1, 1.2) - required `type="text/html"`, HTTPS enforcement, video fallback presence, nonlinear placement, and `apiFramework` casing. |
Expand All @@ -29,6 +31,8 @@ Where vastlint is today and where it's going.
|---|---|
| **Language bindings** | Go bindings shipped. Python, Ruby, and Java bindings in progress - all backed by the same `vastlint-core`. |
| **Erlang / Elixir bindings** | Rustler DirtyCpu NIF - native BEAM terms, zero JSON overhead. `vastlint_nif` crate complete, Elixir/Erlang package scaffolded, precompiled NIF CI pipeline wired. Available on hex.pm shortly. |
| **VMAP validation** | Core rules implemented (23 rules): [VMAP 1.0](https://iabtechlab.com/standards/vmap/) `<AdBreak>` structure, `timeOffset`/`breakType`/`repeatAfter` formats, `<AdSource>` content constraints, VMAP tracking events - plus full VAST validation of inline `<vmap:VASTAdData>` ad data with VMAP-prefixed issue paths. Ships in the next core release; CLI/MCP/web surfaces follow. |
| **DAAST validation** | Core rules implemented (27 rules): [DAAST 1.0](https://iabtechlab.com/standards-old/digital-audio-ad-serving-template-daast/) audio-first deltas from VAST 3.0 - required `<Category>`, `<DAASTAdTagURI>` wrappers, `<AdInteractions>` (with VAST-leftover detection), audio MediaFile attributes, DAAST tracking event set, DAAST pricing models. Ships in the next core release. |

## 🗺️ Upcoming

Expand All @@ -38,8 +42,6 @@ vastlint validates VAST XML. The VAST spec is not a standalone document - it ref

| Milestone | Detail |
|---|---|
| **VMAP validation** | Validate [VMAP 1.0](https://iabtechlab.com/standards/vmap/) documents - the IAB standard for describing ad break schedules that wrap VAST tags. Structural rules for `<AdBreak>`, `<AdSource>`, `<VASTAdData>` inline VAST embeds, `breakType` enum, `timeOffset` format, and repeat/pod constraints. |
| **DAAST validation** | Validate [DAAST 1.0](https://iabtechlab.com/standards/daast/) (Digital Audio Ad Serving Template) documents - the audio-first sibling of VAST that shares most structural elements but replaces `<Linear>` video with `<Audio>` creative types. |
| **IAB Content Taxonomy authority validation** | Validate the `authority` attribute on `<Category>` and `<BlockedAdCategories>` elements against the IAB Content Taxonomy registry - known authority URIs (`iabtechlab.com/IABTC`, `ads.iabtechlab.com`, etc.) and version-qualified formats. |

### Infrastructure
Expand Down
Loading
Loading