ANTO-LTG
Developers

Open catalog, auditable process

Overview

ANTO-LTG is a set of static files: HTML, CSS and native JavaScript for the site, JSON catalogs in catalogs/, and Node scripts that validate the data and generate api/v1/, openapi.json and a search index. There is no server, no database and no framework.

  • It is a research index of official sources with provenance, evidence and review status.
  • It is not a SQL database, a live driver database, a real-time API or a mirror: no installer, firmware or driver binary is stored, hosted or executed.
catalogs/        source of truth (apps, drivers, vendors, tools, bundles, updates) + proposed/ crawler output
schemas/         JSON Schema 2020-12, the single source of truth for validation and OpenAPI
api/v1/          generated: copies of the catalogs, index.json, search-index.json
openapi.json     generated from the schemas
scripts/         build.mjs, crawler/, assets/, curation/, templates/
assets/          css, js (lib/ is unit-tested), icons, images + manifest.json, vendored 7.css
docs/            data model and crawler guides, validated example records
tests/           unit, crawler, e2e (headless browser) and fixtures
.github/         CI configuration, issue and pull-request templates, Dependabot

Open JSON API

Static, read-only files. They change only when the catalogs change and the site is rebuilt. Versioned in the path; schema_version follows semver (additive changes bump the minor number).

EndpointDescriptionItemsSHA-256
Loading...

The full description is openapi.json (OpenAPI 3.1, generated from the schemas). No authentication, no formal uptime or rate-limit promise; do not use it as the only source for a critical action.

curl -s https://YOUR-SITE/api/v1/index.json
curl -s https://YOUR-SITE/api/v1/apps.json | jq '.items[] | select(.winget_id=="Git.Git")'

Data model

Every record has a stable kebab-case id, sources[] (which page supplied which fields, and when) and a verification_status. Schema 1.1.0 is additive over 1.0.0. The full field reference, with every enum value and the verification workflow, is in docs/data-model.md. Pick a catalog to see its fields, generated live from the schema:

FieldTypeRequiredMeaning

Example: a new app record

{
  "id": "example-app",
  "name": "Example App",
  "publisher": "Example Corp",
  "category": "utilities",
  "description": "One factual sentence about what it does.",
  "source_url": "https://example.com/app",
  "source_kind": "publisher_page",
  "publication": { "state": "published", "method": "automated", "checked_at": "2026-10-13T00:00:00.000Z", "checks": ["basic_fields", "https_official_source", "source_recorded", "downloads_pinned", "winget_package_proven"] },
  "verification_status": "not_reviewed",
  "windows_compatibility": "not_reviewed",
  "architectures": [],
  "license": "Unknown",
  "notes": "",
  "sources": [
    { "id": "example-page", "kind": "vendor_page", "url": "https://example.com/app",
      "retrieved_at": "2026-10-13", "fields": ["name", "description", "source_url"] }
  ]
}

Missing facts stay missing: omit version, release_date and downloads rather than guessing. A sha256 is only ever copied from the publisher.

Publication and review

Two separate facts describe every record. Neither one is a safety rating.

  • publication.state published: every automated rule passed when checked_at was recorded. unavailable: a later check found the record no longer meets the rules, so it stays visible with a warning. Publication is decided by scripts/lib/publication.mjs and needs no approval.
  • publication.method: automated (produced by a crawler adapter and published by the merge rules) or maintainer_curated (written from official pages, then checked by the same rules).
  • verification_status not_reviewed: no person has checked the record against the official source yet. This is the normal state of a published record.
  • verification_status verified: a person checked the claims against the official source and recorded reviewed_at, review_notes and an evidence_url. The validator refuses verified without all three, and refuses it for aggregator-sourced driver records.
  • withdrawn: removed from use (kept for history).

windows_compatibility (supported, partial, unsupported) is a human conclusion that also needs notes and evidence. The machine-readable compatibility object only says what the SOURCE declares ("declared", "unsupported" or "unknown") and is never a test result.

Software and scripts

The Software Center only reads apps.json. Selection state lives in localStorage and in portable manifests (schemas/bundle-manifest.schema.json). A manifest restores a selection of catalog ids; install commands are always regenerated from the current catalog, so imported data can never inject a package identifier or a command.

The WinGet script

  • Package IDs must match ^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$; each is placed in a single-quoted, ASCII-only PowerShell string and passed to winget as an argument array: winget install --id <ID> --exact --source winget.
  • The script checks Windows (build 17763 or later; mismatch with the chosen target is a warning), checks that winget.exe exists, prints the plan, and asks you to type YES (case-sensitive). -DryRun previews without installing.
  • It reports failed packages with WinGet's exit codes (taken from winget-cli's returnCodes.md) and writes a short report to the Desktop.
  • No -ExecutionPolicy Bypass, no self-elevation, no download of anything else. The optional download kit only downloads over HTTPS, verifies the SHA-256 published by the source, deletes mismatches and never runs a file.

Drivers

Driver records point at official vendor pages and packages; they never host files. download.kind is one of direct_binary (official domain, stable URL), landing_page, download_form (gated by a license, login, captcha or serial number), redirect, signed_temporary (never stored), unknown or none.

  • vendors.json lists each vendor's official domains. A driver's official_source and any direct link must be on those domains; the validator fails otherwise.
  • Records sourced from a third-party aggregator must be labelled third_party_aggregator, carry download.kind: "none" and point to the vendor's official portal. They can never be verified.
  • Versions, dates, sizes and hashes appear only when the source states them. A hash is copied, never computed.

Crawler

The crawler proposes changes; it never publishes them. See docs/crawler.md for the full guide.

npm run crawl -- winget --dry-run          # fetch and report, write nothing
npm run crawl -- winget                    # write catalogs/proposed/winget.proposals.json
npm run crawl -- winget --retry-failed     # only targets that failed last time
npm run crawl:merge                        # show the merge plan (dry run)
npm run crawl:merge -- --apply             # write catalogs/*.json after validation
npm run crawl:links -- --hosts github.com  # header-only link check
  • Respects robots.txt, a per-host rate limit with backoff, timeouts, a concurrency cap and a descriptive User-Agent; refuses non-allow-listed hosts (including redirect targets), private addresses and non-HTTPS URLs.
  • Prefers official APIs and indexes (the winget adapter reads microsoft/winget-pkgs through the GitHub API).
  • Never downloads binaries (header-only probes), never executes anything, never marks a record verified, and treats crawled text as untrusted (markup is stripped, URLs are validated).

Contributing

  1. Fork the repository and edit the right file in catalogs/ (or add a seed to scripts/crawler/seeds/ and run the crawler).
  2. Cite the official page and the retrieval date in sources[]. Do not add installers, firmware or driver binaries.
  3. Run npm ci && npm run format:catalogs && npm run build && npm test.
  4. Open a pull request that explains the evidence. Before you do, run npm run check (validation, unit and crawler tests, build) and, if you changed the interface, npm run test:e2e (headless-browser tests).

Details and the records checklist are in CONTRIBUTING.md.

Security model

  • The site ships a strict Content-Security-Policy (default-src 'none', scripts and styles only from this origin, no inline code); there are no third-party scripts, fonts or CDNs at runtime.
  • The UI builds DOM with text nodes only (no innerHTML), validates every URL it renders (https only, no credentials, no private hosts) and adds rel="noopener noreferrer" to external links.
  • Catalog text is plain text; markup and control characters are rejected by the validator and stripped by the crawler.
  • No secrets exist in client code. The crawler sends its GitHub token only to api.github.com.

Report vulnerabilities as described in SECURITY.md.

Licensing

Original code is under the MIT license (LICENSE). Third-party material keeps its own license and is listed separately in LICENSING.md: 7.css (MIT), the photographs (Unsplash License and Pexels License, see credits) and data derived from microsoft/winget-pkgs (MIT). Vendor names and logos belong to their owners; ANTO-LTG is independent.