Skip to content

fix(content-lane): protectedFrontmatterFields omits snake_case aliases, letting a protected-field edit bypass the close gate #7445

Description

@JSONbored

Context

packages/loopover-engine/src/review/content-lane/content-repo-spec.ts defines
protectedFrontmatterFields (line 45) — the set of frontmatter keys whose change on a MODIFIED
entry triggers a hard "protected close" via protectedFrontmatterChanges
(src/review/content-lane/duplicates.ts:154). Every entry in this set is written in camelCase only
(downloadUrl, packageUrl, authorProfileUrl, claimUrl, pricingModel, reviewedAt,
reviewedBy, reviewedPrNumber, submittedAt, submittedBy, submittedByUrl,
sourceSubmissionNumber, sourceSubmissionUrl, claimStatus, dateAdded, importPrNumber,
importPrUrl, packageVerified, affiliateUrl).

parseSimpleFrontmatter (src/review/content-lane/duplicates.ts:59) keys parsed frontmatter by
the literal YAML key text with no case normalization. The sibling list urlFields
(content-repo-spec.ts:70) proves snake_case is a genuinely accepted convention for at least two
of these same field names (downloadUrl/download_url, packageUrl/package_url are both
explicitly paired there already). Because protectedFrontmatterFields has no snake_case aliases,
an entry that writes any of these protected fields in snake_case (e.g. download_url: instead of
downloadUrl:) is invisible to protectedFrontmatterChanges — the gate compares
before["downloadUrl"] vs after["downloadUrl"], both undefined, sees no change, and the
protected-close never fires, even when the underlying value was actually changed.

This is the same divergence class issue #7250 already fixed for sourceUrlFields vs urlFields
(closed 2026-07-19, PR #7269) — same file, same root cause (two field-name lists meant to describe
one concept, only one kept in sync with the camelCase/snake_case pairing convention).

Concrete failure scenario: a "modified entry" PR changes an existing entry's download_url:
(or claim_url:, pricing_model:, author_profile_url:, etc. — any snake_case-keyed protected
field) to a different, attacker-controlled value. The identical edit written as downloadUrl:
would be caught by protectedFrontmatterChanges and hard-close the PR as a protected-field
modification; written as download_url:, the gate reports zero protected-field changes and the PR
proceeds through the normal (non-protected) review path — a real gate bypass for supply-chain/
monetization/identity fields, the exact class of edit this gate exists to catch.

Requirements

  • protectedFrontmatterFields must include the snake_case alias for every multi-word camelCase
    member, following the exact pairing convention urlFields already uses: affiliate_url,
    author_profile_url, claim_status, claim_url, date_added, download_url,
    import_pr_number, import_pr_url, package_url, package_verified, pricing_model,
    reviewed_at, reviewed_by, reviewed_pr_number, submitted_at, submitted_by,
    submitted_by_url, source_submission_number, source_submission_url. (author, category,
    disclosure, and slug are single, all-lowercase words — camelCase and snake_case are
    byte-identical for these, so no separate alias is needed or should be added for them.)
  • Do not change protectedFrontmatterChanges's comparison logic itself, duplicates.ts's other
    consumers, or any other field list in content-repo-spec.ts — this is a data-only addition to
    the one constant.
  • The fix must land in packages/loopover-engine/src/review/content-lane/content-repo-spec.ts
    (the real implementation) — src/review/content-lane/content-repo-spec.ts is a
    export * re-export shim (see its own header comment) and picks up the change automatically; do
    not duplicate the constant there.

Deliverables

  • protectedFrontmatterFields in packages/loopover-engine/src/review/content-lane/content-repo-spec.ts extended with the 19 snake_case aliases listed above
  • Regression test in the content-lane test suite: a "modified entry" diff that changes a
    snake_case-keyed protected field (e.g. download_url: from one URL to another, all other
    frontmatter unchanged) is now reported by protectedFrontmatterChanges as a protected-field
    change, matching what the equivalent camelCase-keyed (downloadUrl:) edit already produces
    today
  • A second regression test asserting every camelCase member of protectedFrontmatterFields
    that isn't a single all-lowercase word has its snake_case counterpart also present in the set
    (mirroring the pairing-assertion test content-repo-spec's sourceUrlFields omits the snake_case aliases its sibling urlFields already has #7250's fix added for sourceUrlFields/urlFields)

Test Coverage Requirements

This repo's Codecov patch gate is 99%+ hard (branch-counted) on every changed line/branch in
src/**/packages/**. Both new regression tests above must actually exercise
protectedFrontmatterChanges end-to-end (real before/after frontmatter strings through
parseSimpleFrontmatter), not just assert on the raw Set contents.

Expected Outcome

A content entry that writes any protected field in the accepted snake_case convention is now
protected by the same close gate as its camelCase-keyed equivalent — no more silent bypass of the
identity/provenance/monetization protected-edit gate based purely on which naming convention a
submission happens to use.

Links & Resources

packages/loopover-engine/src/review/content-lane/content-repo-spec.ts:45 (protectedFrontmatterFields,
the incomplete list), :70 (urlFields, the complete camelCase+snake_case pairing to mirror).
src/review/content-lane/duplicates.ts:59 (parseSimpleFrontmatter, no case normalization),
:154 (protectedFrontmatterChanges, the gate this feeds). Issue #7250 / PR #7269 — the identical
fix already applied to sourceUrlFields.

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions