Skip to content

Releases

0.9.0

Choose a tag to compare

@somework somework released this 07 Sep 20:09

Added

  • sitemap --new-only and Sitemap\SeenStoreInterface (wave N, spec 19b §3.5): submit only the URLs that are new
    or changed since the last run of the command, whatever <lastmod> says or does not say. The interface (Implement
    tier: unseen(iterable<SitemapEntry>): iterable<SitemapEntry>, remember(iterable<SitemapEntry>): void) keeps the
    fingerprint of every announced entry — URL plus <lastmod> in ISO 8601, or empty; Console\SitemapRunner takes it
    as the appended, named $seen (SitemapServices::runner(…, seen:) likewise), calls unseen() once after the host
    filter and remember() per batch whose results did not fail — with or without the option, never with --dry-run —
    so a full run followed by scheduled --new-only runs announces each change once. Console\SitemapOptions::$newOnly;
    Console\Definitions::sitemap() declares the option for every adapter. Without a store the option answers
    SitemapRunner::NO_SEEN_STORE (--new-only needs a store of seen URLs; this application has none (the CLI keeps one in its state file).) with exit 2 and reads nothing — the framework adapters have none in this wave; the indexnow
    CLI (indexnowkit/cli) keeps one in its sqlite state file. The summary line gains , N new or changed.
    --changed-since and --new-only add up: the window first, then the store.

Changed

  • Requires indexnowkit/core ^0.13.1.

0.8.0

Choose a tag to compare

@somework somework released this 07 Sep 17:30

Added

  • Console\SitemapRunner takes ?Psr\Clock\ClockInterface $clock = null (appended) and changedSince(?string $option, ?DateTimeImmutable $now = null) counts a relative --changed-since ("1 day") back from $now (wave M, spec 19 §4.9,
    PSR-20): SitemapServices::runner(…, ?ClockInterface $clock = null) passes the graph's clock, so Testing\FrozenClock
    moves the sitemap filter with the debounce window and the submission timestamps. Before, the runner read the wall
    clock through new DateTimeImmutable('-1 day') — the one place of the family a frozen clock could not reach. An
    absolute date is taken as it is, as before.

  • Console\SitemapCommand (wave L, spec 18): the indexnow:sitemap command itself as a symfony/console class over
    Console\SitemapRunner, with #[AsCommand]; Sitemap\Adapter\SitemapServices::command($runner, $sitemapUrlOption)
    builds it. The Symfony bundle and the Yii3 package register this class instead of a copy of their own; an adapter
    without the package registers Console\Command\SitemapNotInstalledCommand of indexnowkit/console under the same
    name. Constructor: (SitemapRunner $runner, string $sitemapUrlOption = 'sitemap.url') — the second names the
    adapter's sitemap.url option in the help.

  • Console\SitemapRunner takes bool $enabled = true (appended) and answers sitemap.enabled is false. with exit 2
    when it is off; SitemapServices::runner() passes SitemapConfig::$enabled. Before, the Yii3 command checked the flag
    itself and the bundle registered no command at all (it still does); the one place is now the runner, whatever the
    adapter chose.

Changed

  • Requires indexnowkit/console ^0.5 (the command classes and the stubs live there).

  • A <loc> on a host this site has no key for is dropped (Console\SitemapRunner), before anything fetches or
    submits it: only the hosts KeyProviderInterface::managedHosts() names — base_url plus the hosts map — pass,
    whatever source produced the entries. One line in the run summary (on stderr with --json) says how many URLs were
    skipped and on which hosts. Nested sitemaps were already restricted to the origin of the root; the entries were not,
    so a sitemap built from user content (or a swapped one) could make the pre-flight of indexnowkit/verify GET
    internal addresses. With no key at all (neither base_url nor a hosts map) nothing can be compared: the entries go
    as they are, with one warning. strict_hosts: true is documented as the recommendation for a sitemap built from user
    content.

  • Sitemap\Adapter\SitemapServices::package() delegates to the core's Adapter\OptionalPackage::sitemap() (core
    0.13.0): the name, the marker and the feature word live there, so an adapter asks about the package without loading
    this class. Same object, same texts; adapters should call OptionalPackage::sitemap() directly.

  • Requires indexnowkit/core ^0.13.

0.7.0

Choose a tag to compare

@somework somework released this 07 Sep 05:31

Added

  • Sitemap\Adapter\SitemapServices — what every framework adapter wires for this package, in one place: package(),
    options(), config(), reader() / readerFor(), spoolCheck(), runner(). The three adapters build on it.

0.6.1

Choose a tag to compare

@somework somework released this 06 Sep 18:50

Changed

  • Requires indexnowkit/core ^0.12.

0.6.0

Choose a tag to compare

@somework somework released this 06 Sep 17:54

Changed

  • The libxml error buffer is cleared before a sitemap is parsed: an error another library left in the process
    (DOMDocument::loadHTML, a SOAP client) was read as this sitemap's and a correct file was refused.
  • <lastmod> without a time zone (2026-09-06) is UTC, not the process time zone; an unparsable <lastmod> is a debug
    line naming the URL instead of silence.
  • A nested sitemap on the same host with an explicit default port (https://x.com:443) is the same origin.
  • A local sitemap index may only reference local parts inside its own directory (<loc>/etc/passwd</loc> was read and
    echoed line by line into the log as a "text sitemap").
  • Requires indexnowkit/core ^0.11.

0.5.1

Choose a tag to compare

@somework somework released this 06 Sep 12:22

Changed

  • Requires indexnowkit/core ^0.10 (Attribute\ParamExtractor became an injected object; nothing else in the core changed).

0.5.0

Choose a tag to compare

@somework somework released this 06 Sep 10:48

Added

  • --no-verify in Console\Definitions::sitemap() and SitemapOptions::$noVerify: SitemapRunner takes an appended
    ?SubmitterFactoryInterface $unverifiedSubmitters and submits through it (a fresh submitter, --force or not) when the
    flag is given — past the pre-flight of indexnowkit/verify the adapters decorate the regular factory with. Without a
    second factory (no verify package) the flag is accepted and changes nothing.

Changed

  • Requires indexnowkit/core ^0.9 and indexnowkit/console ^0.3.

0.4.0

Choose a tag to compare

@somework somework released this 05 Sep 19:25

Changed

  • Requires indexnowkit/core ^0.8 and indexnowkit/console ^0.2.

Added

  • Check\SitemapSpoolCheck lines carry the code sitemap.spool (SitemapSpoolCheck::CODE; core 0.8 check --json).
  • indexnow:sitemap warns after a run without --changed-since that submitted more than batch.max_urls URLs (the
    whole sitemap: engines see every page as changed): run it once, then schedule it with --changed-since (spec 17
    §3.3/§5.7). With --json the warning goes to stderr.

0.3.0

Choose a tag to compare

@somework somework released this 05 Sep 17:24

Changed

  • Requires core 0.7: Console\SubmitterFactory / Console\SubmitterFactoryInterface are now
    IndexNowKit\Adapter\SubmitterFactory / IndexNowKit\Adapter\SubmitterFactoryInterface, Console\ResultSummary is
    IndexNowKit\Submission\ResultSummary. Application code that names them (a decorator of the submitters argument of Console\\SitemapRunner) changes the use line; nothing else.
  • The test suite requires indexnowkit/testing ^0.1 (require-dev): the conformance kits and the H01–H05 assertions
    moved there from the core (Testing\Conformance\KeyFileAssertions, CheckOutputAssertions, ReadmeAssertions).
  • Requires indexnowkit/console ^0.1 and symfony/console: the runners and the formatter Console\SitemapRunner
    builds on moved there from the core with their FQCN unchanged, and the runner renders through SymfonyStyle like
    every command body of the family; symfony/console leaves suggest (it is a requirement now).

Added

  • SitemapConfig::loadOrDisabled(array $block, LoggerInterface $logger, string $checkCommand): the runtime path of
    an adapter — fromArray(), and for an invalid block one critical line indexnow: invalid sitemap configuration, the sitemap command is disabled until it is fixed: {error} (run "{check}") plus disabled(). Replaces the copies
    in Laravel and Yii2 (spec 17 §4.3).

Documentation

  • README: "Notes for AI assistants" (package, minimal complete snippet, verification, pitfalls across the adapters);
    ReadmeAiNotesTest keeps it consistent with the commands and configuration keys.
  • README: --force re-announces URLs inside the debounce window (one-off, not for schedules); batch.max_urls is a
    ceiling, not a target.
  • homepage in composer.json points at the docs site (https://indexnowkit.github.io/php/).

0.2.0

Choose a tag to compare

@somework somework released this 05 Sep 07:41

Changed

  • Requires indexnowkit/core ^0.6 (wave 0a of docs/spec/17: the staging check, the debounce fix). No change in this
    package's own API; upgrade together with the core.

Added

  • psalm.xml and a weekly Psalm taint analysis workflow in the monorepo: the reader parses untrusted XML, so tainted
    data flow is checked separately from the phpstan pipeline. Psalm is not a dev dependency.

Documentation

  • README: the Google paragraph, "notification, not indexing", and what --changed-since relies on (<lastmod>; a
    run without the option re-announces the whole sitemap; lastmod = now() makes every run a full run).