Task: Add admin resolver for bulk updating concept URIs to SEO-friendly URLs

Add admin resolver for bulk updating concept URIs to SEO-friendly URLs

27.08.2026haih agent

Create a secure admin bulk-resolver for migrating old concept URIs to human-readable slugs while preserving redirects.

Objective

Add an administrative GraphQL resolver to haih-agent for the bulk migration of old concepts to human-readable URIs (SEOs / ЧПУ).

Currently, a large number of historical concepts remain in the database whose URIs were created under the old scheme and do not use the new slugifyUri / human-readable format. The new logic works for created and modified entities, but old records do not migrate on their own.

A centralized administrative tool is needed to safely and massively update such URIs.

What the resolver should do

Add an admin-only mutation/resolver that:

  1. Selects concepts that need URI migration.
  2. Computes the target URI for each using current slugifyUri() rules and the entity's current name/hierarchy.
  3. Does not change the URI if it already matches the current format.
  4. When modified, uses the existing common URI change logic (processUriChange or equivalent) to automatically create a 301 redirect from the old address to the new one.
  5. Does not duplicate slugify/redirect rules locally inside the resolver — uses the common haih-agent code.
  6. Returns a clear execution result: how many records were reviewed, how many were modified, how many were skipped, and how many ended in error.

Security and Manageability

The resolver must be strictly administrative.

It is recommended to provide:

  • dryRun to preview future changes without writing to the DB;
  • limit/batch size for migrating in parts;
  • Ability to continue migration using a cursor/offset or another robust method;
  • Filter exclusively for concepts where the URI genuinely requires modification;
  • Logging of oldUri -> newUri;
  • URI collision detection prior to writing;
  • Predictable behavior if two concepts contend for the same URI after slugify;
  • The ability to safely re-run the resolver without re-modifying already migrated entities.

URI Collisions

Define a strategy for collisions separately.

Existing URIs must not be silently overwritten. If the computed slug is already taken by another concept, the resolver should either:

  • skip the record and return the collision in the report;
  • or use a predefined deterministic uniquification strategy.

The strategy must be explicitly fixed in the implementation.

Example Scenario

Was:

/concepts/cmt...

or another historical/technical URI.

For a concept named:

TypeScript Generics

after migration, it should become something like:

/concepts/typescript-generics

At the same time, the old address should continue to work via a 301 redirect.

SEO: Why This Is Needed

This migration is important not only for URL usability, but also as part of the general SEO/GEO strategy for projects based on haih-agent.

1. Semantics Directly in the URL

A technical address like:

/concepts/cmt7tulwi034wtj0qmz5n3s7h

provides search engines with no additional context about the page content.

A human-readable URL like:

/concepts/typescript-generics

contains words that match the topic of the document. The URL becomes another clear signal alongside title, description, headings, and main content.

2. Clearer Snippet and User Trust

A human-readable URL is easier to perceive in SERPs, links, and sharing. Users understand what the page is about even before clicking, instead of seeing a set of technical IDs.

This potentially improves click quality and reduces the perception of a "technical" or opaque page.

3. Stable Migration Without Losing Accumulated Signals

It is critically important not just to replace the URL, but to preserve the old ones via 301.

A 301 allows search engines to understand that the document has moved to a new permanent address and transfer the accumulated signals of the old page to the new URI instead of creating massive 404 errors.

4. Canonical and Eliminating Duplicates

After migration, the human-readable URI should become the canonical address of the page.

Old technical URLs must not be indexed as separate duplicates. A redirect to the canonical human-readable URL should work for them.

5. Bulk Migration of Historical Content

Without a bulk tool, the new SEO-friendly mechanism only affects new and manually edited concepts. Most of the already accumulated content will remain on the old technical URIs and will not benefit from human-readable URLs.

The admin resolver allows bringing the historical body to the new URL model either all at once or in batches.

6. Base for Downstream Projects

Since fi1osof.ru and other projects use haih-agent as a base, the resolver should live specifically inside haih-agent rather than being implemented separately in each application.

This will provide a unified URI migration mechanism for all products on this platform.

Acceptance Criteria

  • Added an admin-only GraphQL resolver/mutation for bulk migration of concept URIs.
  • Uses existing shared slugifyUri logic and URI changes without duplicating algorithms.
  • A 301 redirect is created from the old address for changed URIs.
  • Already correct human-readable URLs are not changed.
  • A secure strategy for handling URI collisions is in place.
  • The resolver can be run repeatedly without corrupting already migrated data.
  • Option to perform migration in batches is available.
  • dryRun is preferably implemented with a report of upcoming changes.
  • The resolver result contains statistics for processed/updated/skipped/errors/collisions.
  • Tests added for regular migration, already current URI, collision, re-run, and redirect creation.
  • After mass migration, old URLs continue to work via 301, and new human-readable URLs can be used as canonical URLs.