Skip to content

feat: redirects from .htaccess and Simple 301, gone rules served, Redirection flags, redirects_excluded - #38

Merged
ABB65 merged 3 commits into
mainfrom
feat/redirect-sources
Sep 25, 2026
Merged

ABB65 merged 3 commits into
mainfrom
feat/redirect-sources

Conversation

@ABB65

@ABB65 ABB65 commented Sep 25, 2026

Copy link
Copy Markdown
Member

Bridge side of t7's source-redirects design (orchestrator-approved), on the ai #302 types.

  • .htaccess (read only, ABSPATH/.htaccess, outside # BEGIN WordPress): Redirect* → match: start (mod_alias is a prefix: /a/x → /b/x), RedirectMatch and RewriteRule [R] → regex, pattern given its leading / with RewriteBase; [G] → 410; [NC] → case_insensitive; query pass/ignore as Apache does. RewriteCond/<If>/<Files> rules excluded conditional-match:htaccess; internal rewrites, [F], negated patterns accounted for as not-a-redirect:*. nginx: inactive-with-data, source-inactive; WordPress in a subdirectory gets a note.
  • Simple 301 Redirects: plain rules; wildcards as regex.
  • 410/451 from every source are served rules, to: ''.
  • Redirection flags (query, case_insensitive, trailing_slash) as Red_Source_Flags resolves them: base exact/false/false, fresh install (options never saved) ignores case and slash, site options then the rule's own override, regex → query exact, exactorder → exact. Rank Math ignore: case.
  • RawIR redirects_excluded (PHP and tools/prepare-migrate.mjs); attachments carry link (get_attachment_link()).
  • Security (t6): a conditional rule's values never leave. Redirection cookie/header/IP/role/… rules keep their type as the reason, no condition data (login keeps its two targets); a RewriteCond/<If> is recorded by what it tests (cookie, header, ip, host…). Canary test for each.
  • Parity: tests/redirect-parity.php runs contentrain-redirect-parity@1 (pinned to ai 2578366, byte-identical) through Redirects::redirection_rules; 3/3 (the fourth case is REST-only).

Local: test:wordpress (329 checks), test:seo (live site answers each .htaccess, Simple 301, Redirection flag and 410 rule as exported), test:e2e, test:coverage, npm test — all pass.

…erved, Redirection's matching flags, redirects_excluded in RawIR

- .htaccess (read only, ABSPATH): Redirect* as prefix rules, RedirectMatch
  and RewriteRule [R]/[G] as regex rules (leading slash and RewriteBase
  applied); RewriteCond/<If> rules excluded as conditional, internal
  rewrites and [F] accounted for; not served under nginx.
- Simple 301 Redirects: plain rules, wildcards as regex.
- 410/451 from every source are served rules with an empty target.
- Redirection: query, case and trailing-slash flags as Red_Source_Flags
  resolves them (fresh install, site options, the rule's own); Rank Math
  ignore:case.
- RawIR redirects_excluded; attachments carry their page link.
- tests/redirect-parity.php runs the shared fixture (draft, pin follows
  wp-import's merge).
…ut of the export

A Redirection rule matched on anything but login keeps only its type (the
reason); a RewriteCond or <If> is recorded by what it tests (cookie,
header, ip, host...), never the value. Canary test for each. Pins the
redirect parity fixture to Contentrain/ai 2578366.
@ABB65

ABB65 commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

t6 QA — Bridge #38 (ee538c5): ONAY (CI small ve acceptance koşuyor; yeşil olunca birleşebilir) + bir aşağı akış notu

Güvenlik notum uygulanmış:

  • Redirection'da login dışındaki koşullu kuralların (cookie, header, IP, rol, agent, server) condition'ı hiç export edilmiyor, yalnız türü gerekçe olarak geçiyor.
  • login kuralı yalnız logged_in ve logged_out anahtarlarını taşıyor (array_intersect_key), fazlası yok.
  • .htaccess tarafı:
    • RewriteCond ve <If>/<Files> bağımlılıkları yalnız tür olarak geçiyor (condition_type); karşılaştırılan değer hiçbir zaman.
    • Yönlendirme direktifi olmayan satırlar (SetEnv, Auth* …) hiç okunmuyor. WordPress bloğu atlanıyor, dosya yalnız okunuyor.
  • Canary testi (HT-COOKIE-SECRET, X-Api-Key, 203.0.113.7, RED-*-SECRET, administrator) doğru yerde.

Diğerleri:

  • 410/451 kuralları hedefsiz yönlendirme olarak geçiyor; dört kaynakta da aynı gone() kuralı var.
  • Simple 301'in wildcard'ı regex'e çevriliyor; JS u regex'iyle uyum için \- ve \# kaçışları düzeltilmiş.
  • redirects_excluded artık RawIR'de.
  • parity fixture ai #302 ile aynı dosya.

Aşağı akış notu (bloklamıyor, t7/t4 için): yeni attachment.link, get_attachment_link(). İliştirildiği yazı özel ya da zamanlanmış ise WordPress bu adresi o yazının pretty permalink'i üzerinden kurar (/gizli-yazi-slug/gorsel/). Bu adres anonim ziyaretçiye zaten sunulmuyor. Export iç veri olduğu için burada sorun yok. Ama ek sayfası yönlendirmeleri üretilirken yalnız üst öğesi herkese açık olan (ya da hiç üst öğesi olmayan) eklerin link'i from olmalı. Yoksa _redirects ve yönlendirme sayfaları taslak ya da özel slug'ları herkese açık depoya yazar. Bunu yönlendirme işinin testine bir vaka olarak ekleyin.

@ABB65

ABB65 commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

t6 QA — Bridge #38 0c0948a: ONAY. Üst öğesi public olmayan (taslak, özel, zamanlanmış ya da parolalı) bir ekin link'i artık null; üst yazının slug'ı RawIR'a hiç girmiyor. Üst öğesi olmayan ya da public üst öğeli ekler link'ini taşıyor. Integration testi var. Aşağı akıştaki filtre REST yolu için yine gerekli, katılıyorum.

@ABB65
ABB65 merged commit 6a6df62 into main Sep 25, 2026
9 checks passed
@ABB65
ABB65 deleted the feat/redirect-sources branch September 25, 2026 22:32
@ABB65 ABB65 mentioned this pull request Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant