Skip to content

Releases

0.15.0

Choose a tag to compare

@somework somework released this 07 Sep 17:35

Added

  • indexnowkit.clock (Clock\SystemClock, aliased to Psr\Clock\ClockInterface): the one service every piece
    that reads the time takes it from — indexnowkit.throttle, the memory indexnowkit.debounce_store,
    indexnowkit.submitter, indexnowkit.command_submitter_factory and, with verify.enabled, the pre-flight
    decorators. Replace it with IndexNowKit\Testing\FrozenClock in a compiler pass and the debounce window, the
    throttle window and the time a submission record gets all move together (audit 0.13 A5; docs/extending.md,
    docs/testing.md).
  • indexnowkit.check.locales (the core's Check\LocalesCheck over Check\MappedClasses, code router.locales):
    one indexnow:check warning when a #[IndexNow(locales: 'all')] rule meets an empty framework.enabled_locales,
    which until now silently produced one URL without a locale instead of one per locale (audit 0.13 W14; the class
    moved to the core in wave M, spec 19 §4.4, one text for the three adapters that print it).
  • The router bridge warns once per process when locales: 'all' meets an empty framework.enabled_locales
    (indexnowkit.route_url_resolver takes the logger now, on the indexnow channel): the rule silently collapsing
    to one URL was, until now, a line of check only. The expansion, the pinned origin and the exception text are the
    core's Url\RouteOrigin (wave M, spec 19 §4.6).

Changed

  • Wave M (spec 19): the bundle's copies of what the family shares are the core's or the packages' classes.
    Check\LocalesCheck and Check\EntitySampler are removed — the service ids stay (indexnowkit.check.locales is the
    core's Check\LocalesCheck over the new Check\MappedClasses, indexnowkit.check.entity_sampler.callable is
    Console\SubjectSampler of indexnowkit/console). Command\EntityLoader extends Console\AbstractSubjectLoader
    (its constructor and manager() are unchanged). Messenger\MessengerDispatcher is the Messenger push around the
    core's Dispatch\BatchingDispatcher: its constructor takes the Config (indexnowkit.config) where it took
    $logUrls and $batchMaxUrls — an internal service (indexnowkit.dispatcher), not in docs/bc.md — and its log
    lines are the core's ({count} URL(s) queued as message {id}, cannot queue {count} URL(s) (message {id}), they are lost: {error}; docs/messenger.md). SubmitUrlsMessage::newId() delegates to BatchingDispatcher::newJobId().
    EventListener\FlushListener takes (CollectorInterface, Closure(): IndexNowKit) instead of a PSR-11 service
    locator (PSR-11 says a container should not be passed in for an object to fetch its own dependencies; a
    service_closure('indexnowkit') is as lazy). Migration: a FlushListener built by hand passes
    static fn () => $container->get('indexnowkit'). Check\CacheProbe writes the core's DebounceStoreCheck::PROBE_KEY
    (it only read a key). The nine literal 'memory' / 'none' comparisons of the loader are
    DebounceStoreFactory::isShared(); the status line of the debounce store is HistoryServices::describeStore()
    of indexnowkit/history (cache.app (missing) when the pool is not a service, where the bundle printed the bare id).

  • The command classes are the packages', Command\* of the bundle is gone (wave L, spec 18). indexnow:check,
    indexnow:config, indexnow:submit, indexnow:submit-entity, indexnow:explain, indexnow:key:generate and the
    three "not installed" stubs are IndexNowKit\Console\Command\* of indexnowkit/console 0.5 (submit-entity is
    SubmitSubjectsCommand, named by the vocabulary), indexnow:sitemap is IndexNowKit\Sitemap\Console\SitemapCommand
    (sitemap 0.8), indexnow:history and indexnow:status are IndexNowKit\History\Console\HistoryCommand /
    StatusCommand (history 0.4). The bundle registers them under their class names with the same runners
    (indexnowkit.console.*), the same names, arguments, options, exit codes and --json; the Yii3 package registers
    the very same classes. What check and config read is DependencyInjection\ConsoleConfigSource
    (indexnowkit.console.config_source, a Console\ConfigSourceInterface) instead of three constructor arguments.
    Every console.command stays lazy (#[AsCommand], or the command + description attributes of the tag for
    SubmitSubjectsCommand), which the bundle's own test now asserts. Command\EntityLoader stays where it is.
    Migration: only a direct reference to IndexNowKit\SymfonyBundle\Command\*Command breaks — a decorates: on one of
    those ids, an instanceof, a #[AsCommand] subclass (they were final). Decorate the runner instead
    (indexnowkit.console.submit_entity, …), or register a command of your own under the same name
    (docs/extending.md "Replacing a command").

  • The --sample gate of indexnow:check is the core's: indexnowkit.check.samples is
    IndexNowKit\Check\SampleOptions and indexnowkit.check.verify_sample is IndexNowKit\Check\SampleGateCheck
    (core 0.13.0) instead of the bundle's own byte-identical copies, which are removed —
    IndexNowKit\SymfonyBundle\Check\SampleOptions and IndexNowKit\SymfonyBundle\Check\VerifySampleCheck are gone.
    Same service ids, same lines, same verify.installed code; only a direct reference to those two classes breaks
    (audit 0.13 A2).

  • indexnowkit.verify.submitter and indexnowkit.verify.command_submitter_factory pass their arguments by name
    ($inner, $transport, …) rather than by position, so a parameter added to Verify\VerifyingSubmitter fails the
    compilation instead of shifting values into the wrong slots (audit 0.13 A16).

  • DispatcherFactory::SYNC instead of the 'sync' literal in DependencyInjection\VerifyServices (audit 0.13 A19).

Fixed

  • The profiler panel no longer prints the submission store's raw exception message: a failing store shows the
    exception class plus a message whose DSN credentials are masked the way indexnow:config masks them, so a panel
    screenshot in a bug report carries no database user or password (audit 0.13 S12).
  • Fixed: the bundle was a fatal without indexnowkit/sitemap, indexnowkit/verify or indexnowkit/history
    (Class "IndexNowKit\Sitemap\Adapter\SitemapServices" not found while compiling the container): the configuration
    tree and the loader asked the packages' *Services::package() whether the package is installed, and those classes
    live in the packages. They now ask the core's Adapter\OptionalPackage::sitemap() / verify() / history()
    (core 0.13.0); DependencyInjection\{Sitemap,Verify,History}Services::package() delegate there too. Same texts, same
    service ids. A new CI job removes the three packages and boots the bundle with detection
    (OptionalPackagesDetectionTest).
  • Requires indexnowkit/core ^0.13, indexnowkit/console ^0.5, and indexnowkit/history ^0.4 when installed
    (conflict with older).

Tests

  • The kernels of the functional suite put a fingerprint of the bundle's sources in the container cache path: with
    debug: false Symfony never checks the compiled container for freshness, so a local edit of the DI extension was
    tested against the previous container (audit 0.13 T10).
  • The in-memory Messenger transport of the messenger* variants runs with ?serialize=true, so the message and its
    stamps are really encoded and decoded instead of being handed back as the same object (audit 0.13 T17).
  • A #[IndexNow(resolver: ...)] id the container knows but cannot build, and one it does not know at all, are
    asserted to carry the family's ConfigurationException texts, which now come from the core's
    Url\ArrayResolverLocator (audit 0.13 A10).

0.14.0

Choose a tag to compare

@somework somework released this 07 Sep 05:31

Changed

  • The optional packages wire themselves: DependencyInjection\{Verify,History,Sitemap}Services keep the service ids,
    the configuration nodes and the definitions but take the predicate, the check line, the sample check factory, the PDO
    of a DSN, the 403 counter and the status runner from Verify\Adapter\VerifyServices, History\Adapter\HistoryServices
    and Sitemap\Adapter\SitemapServices of the packages (verify 0.3, history 0.3, sitemap 0.7 — conflict with older
    ones). indexnowkit.check.verify is built by the package from indexnowkit.verify_config (same text).
  • Requires indexnowkit/verify ^0.3, indexnowkit/history ^0.3, indexnowkit/sitemap ^0.7 when installed.

0.13.0

Choose a tag to compare

@somework somework released this 06 Sep 18:50

Added

  • Symfony 8 (^6.4 || ^7.0 || ^8.0 on every symfony/* requirement; the README said "6.4 | 7 | 8" since 0.11 while
    composer.json capped at 7 — the two agree now). CI runs the bundle on Symfony 8 with PHP 8.4 (ci:install:symfony8).

Changed

  • Wiring follows core 0.12.0: AttributeUrlResolver::fromConfig() and ObjectChangeHandler take the ParamExtractor
    as their third argument (the service indexnowkit.param_extractor, unchanged).
  • Requires indexnowkit/core ^0.12.

0.12.0

Choose a tag to compare

@somework somework released this 06 Sep 17:54

Changed

  • Messenger\SubmitUrlsHandler re-queues only the rejected URLs of a partially accepted batch, as a new
    SubmitUrlsMessage with the same id and the engine's Retry-After as a DelayStamp; the whole message is thrown back
    to the transport only when every URL was rejected. Before, a Retry-After longer than debounce.per_url re-sent the
    accepted URLs too.
  • Messenger\MessengerDispatcher sends one message per batch.max_urls URLs: a bulk import of 500 000 rows was one
    message a transport with a size limit (SQS) rejected, and every URL was lost with one log line.
  • check gets verify.transport (an application http.client with verify) and the verify.dispatch line comes from
    Verify\Check\DispatchCheck.
  • indexnowkit.verify configuration: time_budget.
  • Requires indexnowkit/core ^0.11, indexnowkit/console ^0.4; tests against verify ^0.2, history ^0.2, sitemap ^0.6, doctrine ^0.8.

0.11.0

Choose a tag to compare

@somework somework released this 06 Sep 12:23

Added

  • indexnowkit.param_extractor (alias IndexNowKit\Attribute\ParamExtractor): how params and when are read off
    entities — the core DSL plus every service implementing Attribute\SubjectReaderInterface, which is autoconfigured with
    the tag indexnowkit.subject_reader (a reader for objects the DSL cannot see into: a CMS record behind get_field()).
    The resolver, the change handler, the facade and indexnow:explain share it.

Changed

  • Requires indexnowkit/core ^0.10.

0.10.0

Choose a tag to compare

@somework somework released this 06 Sep 10:48

Added

  • indexnowkit/verify wiring (spec 17 §6.1). With the package installed the verify node is the full tree
    (enabled, redirect, non_canonical, origin_error, delay, timeout, max_redirects, max_batch,
    robots_cache_ttl, user_agent; DependencyInjection\VerifyServices); with verify.enabled: true
    indexnowkit.submitter and indexnowkit.command_submitter_factory are decorated by VerifyingSubmitter /
    VerifyingSubmitterFactory, so dispatch: sync, the Messenger handler, the profiler recorder and every command
    verify; Submitter::class keeps pointing at the plain submitter; indexnowkit.command_submitter_factory.unverified
    is the plain factory (for the --no-verify flag of indexnow:sitemap). New services: indexnowkit.verify_config,
    indexnowkit.verify.transport (verify.timeout, verify.user_agent, your http.client), indexnowkit.verify.robots.
    check lines: verify.installed (verify: installed, disabled (verify.enabled: false) / verify: enabled (…)),
    verify.dispatch (warning with dispatch: sync), verify.sample. Without the package the verify block is
    accepted and ignored (check says so) and --sample is an error naming the install line.
  • indexnow:check --sample=<url> / --sample-class=<FQCN>[:<id>] (repeatable; Check\SampleOptions,
    Check\VerifySampleCheck, Check\EntitySampler over indexnowkit.entity_loader with Doctrine).
  • indexnow:config --json prints the verify section when the package is installed.
  • indexnowkit/history wiring (spec 17 §6.2). With the package installed the history node is the full tree
    (store, limit, key_prefix, pdo.dsn, pdo.service, pdo.table, retention_days;
    DependencyInjection\HistoryServices); with history.store: psr16 or pdo the package's store is
    indexnowkit.submission_store (alias indexnowkit.history.store), so the submitter, the Messenger handler, the
    commands and the verify decorator record into it — an application service under that id still replaces it.
    psr16 uses the debounce pool's PSR-16 view (or cache.app with debounce.store: memory|none); pdo takes the
    Doctrine connection of pdo.service (a connection name or a service id, getNativeConnection()) or a PDO built
    from pdo.dsn — never both — and does not create the table (see the package's docs/migrations.md). New services:
    indexnowkit.history_config, indexnowkit.history.pdo / indexnowkit.history.cache, indexnowkit.forbidden_counter
    (Retry\ForbiddenCounter), indexnowkit.console.history, indexnowkit.console.status. Commands
    indexnow:history (--host, --status, --url, --since, --limit, --json, --purge[=days]) and
    indexnow:status (--json per the package's status.schema.json; the Messenger transport and bus as the
    adapter facts); without the package Command\HistoryNotInstalledCommand / StatusNotInstalledCommand print the
    install line and exit 1. check lines: history.installed (without the package), history.store,
    history.records. config --json gets the history section. The profiler panel lists the last 20 recorded
    submissions ("Recent submissions"; IndexNowDataCollector takes an appended ?SubmissionStoreInterface $history).
  • IndexNowKitBundle(?bool $sitemapInstalled = null, ?bool $verifyInstalled = null, ?bool $historyInstalled = null)
    (appended), the same on IndexNowKitConfiguration and IndexNowKitLoader; parameter indexnowkit.debounce.key_prefix;
    DependencyInjection\TransportFactory::create(..., array $extraHeaders = []).

Changed

  • Requires indexnowkit/core ^0.9, indexnowkit/console ^0.3 and (dev/suggest) indexnowkit/sitemap ^0.5,
    indexnowkit/doctrine ^0.7, indexnowkit/verify ^0.1, indexnowkit/history ^0.1.

0.9.0

Choose a tag to compare

@somework somework released this 05 Sep 19:25

Changed

  • Requires indexnowkit/core ^0.8, indexnowkit/console ^0.2 and (dev/suggest) indexnowkit/sitemap ^0.4, indexnowkit/doctrine ^0.6. Core 0.8 strips tracking parameters by default (normalizer.strip_tracking_params) and makes Equals in params an error (see the core changelog).

Added

  • The indexnow:check lines of the bundle carry stable codes (core 0.8, check --json): wiring.messenger,
    wiring.doctrine, plus the core's debounce.store and sitemap.installed. Listed in the core's docs/check-codes.md.
  • indexnow:check --json (the report as JSON, schema docs/check.schema.json of indexnowkit/console), --strict
    (warnings fail the command: put it in the deploy pipeline) and a repeatable --host (console 0.2).
  • indexnow:key:generate --force keeps the replaced key as INDEXNOW_PREVIOUS_KEY and refuses a second rotation while
    it is set; --no-previous and --yes decide (console 0.2).
  • The 403 escalation of Client counts in the PSR-16 view of the debounce.store pool (core 0.8): one critical
    line per streak for every worker of the application; with memory/none the counter stays per process.
  • Service indexnowkit.submission_store (alias Submission\SubmissionStoreInterface, NullSubmissionStore by default):
    the store the submitter and the command submitters record every Result in (core 0.8); replace it with your own or
    with the indexnowkit/history package.
  • Configuration block normalizer (strip_tracking_params, tracking_params, trailing_slash, sort_query): the
    canonical form of every URL (core 0.8). indexnowkit.url_normalizer is now built by Url\UrlNormalizerFactory
    from the configuration; tracking parameters are stripped by default.
  • indexnow:explain --json and the when values in the text output (console 0.2).
  • indexnow:config (--json): the effective configuration with masked keys plus this adapter's own keys (console 0.2).

0.8.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 indexnowkit.command_submitter_factory) 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: the runners and definitions the commands are built on moved there from the core
    with their FQCN unchanged (IndexNowKit\Console\*); Composer installs it with this package, nothing to do.
  • The sitemap predicate is an IndexNowKit\Adapter\OptionalPackage (DependencyInjection\SitemapServices::package());
    the bundle's sitemapInstalled constructor argument is unchanged. IndexNowKitLoader::SITEMAP_MISSING,
    SITEMAP_MISSING_BLOCK_IGNORED and Command\SitemapNotInstalledCommand::MESSAGE are gone (the texts come from the
    package object; DependencyInjection\* is wiring, not API). The check line for a configured but ignored sitemap
    block is a warning now (it was ok).

Documentation

  • README: the quick-start entity is tests/Readme/Post.php verbatim (complete use lines, the category relation the
    via: rule reads, casts/defaults that make it run); ReadmeQuickstartTest compares the README block with the file
    and runs the entity through the test application against the FakeTransport.
  • 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 "Operations": the production checklist first, then monitoring rules, deleted pages, what not to submit,
    multi-domain and troubleshooting. docs/troubleshooting.md: "Staging submitted its URLs" and "Duplicates with
    memory and several workers". docs/multi-domain.md: www and apex, hreflang clusters through locales: 'all' /
    locale_hosts / via:.
  • Russian translation: docs/troubleshooting.ru.md (linked from README.ru.md).
  • homepage in composer.json points at the docs site (https://indexnowkit.github.io/php/).

0.7.0

Choose a tag to compare

@somework somework released this 05 Sep 07:41

Wave 0a of docs/spec/17 with core 0.6.0. indexnow:check fails in a non-production kernel environment when a key
is configured and dry_run is not set
(a staging copy with the production key submits real URLs). A staging or
preview environment that submits on purpose says dry_run: false in its configuration and gets a warning instead.
The Flex recipe's dry_run: true in dev and test is unaffected.

Changed

  • Requires indexnowkit/core ^0.6; indexnowkit/doctrine ^0.4 and indexnowkit/sitemap ^0.2 when installed.
  • The dry_run node of the configuration has no default any more: an unset dry_run stays unset so the core can tell
    it from an explicit false. Reading dry_run from the processed configuration array (not from Config) now needs
    ?? false.

Added

  • debounce line in indexnow:check through the core DebounceStoreCheck and the bundle's Check\CacheProbe:
    the configured pool is read through the same Psr16Cache the store uses and named (debounce: 600s per URL, shared through cache pool "cache.app" (RedisAdapter)); an unusable pool is an error, memory a per-process
    warning, none and per_url: 0 ok lines. Parity with the Laravel and Yii2 adapters.
  • internetarchive and amazon accepted in engines (core 0.6).

Documentation

  • docs/bc.md: configuration keys, command names and options, the service ids of extending.md, the
    container parameters, public classes and the route. README: "Why this over X", "Notification, not indexing",
    the issues link, the badges in the family order.

0.6.1

Choose a tag to compare

@somework somework released this 04 Sep 21:02

Changed

  • Internal refactor, no API change: DependencyInjection\IndexNowKitLoader::load() is a sequence of private methods
    per block of services (config, http, pipeline, urls, dispatch, facade, key file, profiler, checks, console,
    doctrine). Service ids, arguments, tags, aliases and their registration order are unchanged; a new
    ContainerShapeTest records them per configuration variant and fails on any difference.