Skip to content

Recognize an intentional payload projection instead of rejecting it as an unsafe symlink #60

Description

@dapi

Переформулировано. Исходно issue просил --scope memory-bank/ для pull. Это была неверная постановка: она исходила из того, что репозиторий-источник шаблона держит у себя копию payload. Он не должен её держать — и CLI сам это утверждает (см. ниже). Настоящий запрос другой.

Топология

Репозиторий dapi/memory-bank — источник шаблона и одновременно его потребитель: template/memory-bank/ — payload, memory-bank/ — project-local Memory Bank этого проекта.

Копии payload там больше нет. Generic-документы представлены симлинками в payload по соответствующему пути:

memory-bank/flows/routing.md -> ../../template/memory-bank/flows/routing.md
memory-bank/dna/principles.md -> ../../template/memory-bank/dna/principles.md

Реальными файлами остаются только те документы, которыми владеет или которые переопределяет проект. Это не обходной приём, а осознанная модель: инстанс равен payload по построению, синхронизировать нечего, дрейфа не существует.

Что делает CLI сегодня

1. doctor считает такой симлинк дефектом, если файл числится в lock:

error  manifest.managed_unreadable  memory-bank/flows/routing.md
       Managed file cannot be inspected: unsafe symlink in path "memory-bank/flows/routing.md"
       remediation: Restore the file from the pinned template with memory-bank-cli pull.

При полной проекции это 110 ошибок — по одной на документ.

2. pull и init останавливаются на unsafe path ещё до чтения, если симлинк встречается в любом компоненте пути назначения.

3. lint при этом работает корректно — читает сквозь файловый симлинк, документ попадает в область, навигация и индексы проверяются как обычно.

То есть инструменты расходятся между собой: для lint проекция — нормальный документ, для doctor — неисправность.

Почему строгое правило верно в общем случае и промахивается здесь

Запрет нужен, чтобы запись не ушла за пределы репозитория по подменённой ссылке. Это правильная защита для записи по destination path.

Но у проекции цель разрешается внутрь того же репозитория, ровно в тот payload-файл, которым CLI и так управляет. Ни выхода за корень, ни traversal, ни TOCTOU-подмены: цель — соседний путь в том же коммите.

Показательно, что CLI уже знает про эту топологию. Стоит убрать lock, и он сам формулирует правило:

$ memory-bank-cli doctor --profile template
info  template.source_repository  Template source profile detected;
      an installed-template lock is not expected.
      remediation: Create locks only in downstream repositories through memory-bank-cli init.
Result: 0 error(s), 0 warning(s), 1 info

Если репозиторию-источнику не положен lock, то не положена и копия. Проекция — прямое следствие этого же правила, просто CLI пока о ней не знает.

Предлагаемое поведение

  • Симлинк под memory-bank/, чья цель после разрешения остаётся внутри корня репозитория и указывает на template/memory-bank/<тот же относительный путь>, считать намеренной проекцией, а не managed_unreadable. В профиле template это нормальное состояние, максимум — info.
  • Продолжать отклонять симлинки, которые разрешаются за пределы корня или указывают не на соответствующий payload-файл: именно они и опасны.
  • Для pull и init как минимум различать эти два случая в тексте ошибки. Сейчас сообщение одинаковое, и оператор не понимает, наткнулся он на защиту от traversal или на осознанную конструкцию своего же репозитория.

Побочная находка: lint и симлинки на директории

lint читает сквозь симлинк на файл, но не спускается в симлинк на директорию. Замена memory-bank/flows одним симлинком на template/memory-bank/flows уронила область со 120 файлов до 68, и все ссылки внутрь flows/ были объявлены битыми — без единого предупреждения о том, что каталог просто не обошли.

Из-за этого проекцию пришлось делать пофайловой (110 симлинков вместо 8 каталожных). Само по себе терпимо, но разное отношение к файловым и каталожным симлинкам стоит либо выровнять, либо назвать явно в диагностике.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions