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
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:
- Selects concepts that need URI migration.
- Computes the target URI for each using current
slugifyUri()rules and the entity's current name/hierarchy. - Does not change the URI if it already matches the current format.
- When modified, uses the existing common URI change logic (
processUriChangeor equivalent) to automatically create a301redirect from the old address to the new one. - Does not duplicate slugify/redirect rules locally inside the resolver — uses the common
haih-agentcode. - 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:
dryRunto 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
slugifyUrilogic and URI changes without duplicating algorithms. - A
301redirect 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.
-
dryRunis 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.