콘텐츠로 이동

백포트 빌더의 보안 및 운영

빌드 도구이지 런타임 의존성이 아닙니다. 이 페이지는 빌드 파이프라인을 어떻게 운영하고 신뢰할지 다룹니다. PDF 엔진 자체의 보안 태세는 이 페이지가 아니라 엔진 문서에서 다룹니다.

빌더는 자신이 작성하지 않은 소스를 변환하고, 원래 대상으로 삼아 개발된 것이 아닌 배포본을 생성합니다. 따라서 보안 모델도 여기서 출발합니다. 신뢰 경계는 소스 체크아웃과 툴체인입니다. 생성된 아티팩트는 기계가 생성한 읽기 전용 결과물입니다. 공개 패키지와 Pro 패키지 간의 라이선스 분리는 코드에 고정되어 있습니다.

빌더의 입력은 소스 저장소와 고정된 툴체인입니다. 출력은 파생된 아티팩트입니다. 다음 세 가지 속성이 적용됩니다:

  • 생성된 배포본은 읽기 전용이며 기계가 생성합니다. 이 배포본은 이 저장소의 브랜치가 아니라 버전 태그로 게시됩니다. 개발, 버그 보고, 기능 요청은 생성된 트리가 아니라 원본 nextpdf/* 소스 저장소로 보냅니다. 프로젝트 README.md 주의 블록과 .github/workflows/build.yml에서 검증되었습니다(릴리스가 생성된 트리를 새로 커밋하고 태그합니다).
  • 릴리스 토큰의 범위는 좁습니다. secrets.BACKPORT_TRIGGER_TOKEN은 릴리스 태그에서 소스 저장소를 복제하도록 허용합니다. 이 토큰은 소스 체크아웃 단계에서만 참조됩니다. build.yml에서 검증되었습니다(GH_TOKEN 사용).
  • CI 러너 분리는 의도적입니다. 신뢰된 이벤트는 자체 호스팅 PHP 러너에서 실행되며, 포크 풀 리퀘스트와 Dependabot 실행은 GitHub 호스팅 러너로 강제됩니다. 신뢰할 수 없는 코드는 신뢰된 러너 풀에서 절대 실행되지 않습니다. .github/workflows/0-ci.yml에서 검증되었습니다(runs-on 조건문).
  • 툴체인은 composer.json에서 제약됩니다. Rector ^2.0, PHPStan ^2.1, PHPUnit ^13.0, 그리고 symfony/polyfill-* 세트입니다. 빌더에는 NextPDF 런타임 의존성이 없으므로, NextPDF 런타임 패키지가 침해되어도 빌더에는 도달할 수 없습니다. composer.json에서 검증되었습니다.
  • 의존성 업데이트는 봇 기반이며 게이트됩니다. Dependabot 구성과 자동 병합 워크플로가 마련되어 있습니다. Dependabot 실행은 GitHub 호스팅 러너로 고정되며, 병합 전에는 여전히 전체 CI 게이트(PHPStan, 테스트, 드라이런)를 통과해야 합니다. .github/dependabot.yml.github/workflows/0-ci.yml, 9-dependabot-auto-merge.yml에서 검증되었습니다.
  • 출력에는 빌드 상태가 제외됩니다. 릴리스 아카이브는 vendor/.git/를 제외하고 압축되므로, 게시된 아티팩트에는 빌더 자신의 의존성 트리가 아니라 소스와 생성된 매니페스트가 담깁니다. build.yml에서 검증되었습니다(zip ... -x '*/vendor/*' '*/.git/*').
  • 정적 분석이 빌드 코드를 게이트합니다. composer analyse는 두 영구 브랜치 어느 쪽이든 모든 푸시와 풀 리퀘스트에서 rector/rulesscripts에 대해 레벨 10으로 PHPStan을 실행합니다. 이는 모든 드라이런보다 먼저 실행됩니다. composer.json0-ci.yml에서 검증되었습니다.

빌드 스크립트는 출력 구문을 로컬에서 검사하지 않습니다. 빌드 호스트가 대상보다 더 새로운 PHP를 실행하기 때문입니다. 최종 권한을 갖는 게이트는 릴리스 워크플로에 있습니다. 빌드 후 러너는 대상 PHP로 전환하여 output/src 전체에 php -l을 실행하고, 파싱 오류나 치명적 오류가 하나라도 있으면 릴리스를 실패시킵니다. 그런 다음 아티팩트는 검증 매트릭스 전반에 걸쳐 설치되어 실행됩니다 — PHP 8.1 레인은 PHP 8.1부터 8.4까지, PHP 7.4 레인은 PHP 7.4와 8.0입니다. 대상 런타임이 거부할 배포본은 릴리스 단계에 도달하지 못합니다. scripts/build.php(validateOutput()) 및 .github/workflows/build.yml(구문 검사 및 validate-* 작업)에서 검증되었습니다.

이는 파이프라인이 실행하는 런타임으로 범위가 한정된 관찰 기반 동작 보장입니다. 적합성 인증이 아닙니다. 구문 수용과 프로젝트 자체 테스트 스위트를 넘어서는 변환된 프로그램의 정확성을 보장하지 않습니다.

생성되는 두 패키지에는 서로 다른 라이선스가 적용되며, 이는 scripts/adjust-composer.php에 고정되어 있습니다:

패키지라이선스 필드설정 위치
nextpdf/backportApache-2.0generatePublicComposer()
nextpdf/backport-proproprietarygenerateProComposer()

빌더 저장소 자체는 Apache-2.0입니다(composer.jsonlicense). CHANGELOG.md는 LGPL-3.0-or-later에서 Apache-2.0으로 이전한 재라이선싱을 기록합니다. 그 변경 이전에 게시된 버전은 이전 라이선스 아래 그대로 남아 조회 가능하게 유지되며, 모든 새 버전은 Apache-2.0입니다. Pro 배포본은 독점 라이선스이며, PHP 8.1 대상으로만 생성되고, phpseclib/phpseclib ^3.0을 필요로 합니다. CHANGELOG.md, composer.json, 그리고 scripts/adjust-composer.php에서 검증되었습니다.

코드가 강제하는 범위 안에서 파이프라인이 보장하는 것:

  • 첫 실패 시 중단. 빌드는 첫 번째로 실패하는 단계에서 이름이 표시된 오류와 함께 중단됩니다. 릴리스 작업이 성공한 빌드와 검증에 의존하므로 부분적인 배포본은 절대 릴리스되지 않습니다. scripts/build.php(step()) 및 build.yml 작업 needs에서 검증되었습니다.
  • 직렬화된 빌드. cancel-in-progress: false를 가진 backport-build 동시성 그룹은 두 소스 릴리스가 동일한 릴리스 태그를 두고 경합하지 않도록 합니다. build.yml에서 검증되었습니다.
  • 재현 가능한 입력. 파이프라인은 빌드하기 전에 모든 소스 저장소를 정확한 릴리스 태그에서 복제합니다. build.yml에서 검증되었습니다(--branch "${TAG}").

이것이 주장하지 않는 것:

  • 이는 표준 적합성, 완전한 PHP 버전 호환성, 또는 구문 수용과 테스트 스위트를 넘어서는 변환된 프로그램의 정확성을 인증하지 않습니다.
  • 다운그레이드는 런타임에서 강제되는 불변성을 제거합니다(readonly 제거). readonly 속성 쓰기 거부를 런타임에 의존하던 코드는 다운그레이드된 출력에서 그 방어를 잃습니다. 이는 clone-with 안전성을 위한, 문서화된 의도적 절충입니다 — /integrations/backport/troubleshooting/ 를 참고하세요.

빌더 보안 문제는 저장소의 SECURITY.md를 따릅니다: 공개 이슈가 아니라 GitHub Security Advisory 또는 보안 연락처를 통해 보고하세요. 생성된 코드의 문제는 원본 소스 저장소에 제기해야 합니다. 생성된 트리는 기계가 생성한 것이며 개발 대상이 아니기 때문입니다. SECURITY.md와 프로젝트 README.md에서 검증되었습니다.

  • /integrations/backport/overview/ — 빌더가 무엇이고 무엇을 생성하는지.
  • /integrations/backport/production-usage/ — 릴리스 파이프라인을 운영하는 방법.