Skip to content

naruon: split frontend and backend runtime images #1022

Open

Description

@seonghobae

최신 검증 연결 — 2026-09-07

기존 owner PR #1365의 head는 9b137f25f426743e18fc61125575ec7949d45db8다. 명시적 runtime target, OCI 기본 라벨, JSON 실행 명령, 가상환경 제외, PR 출력 설정을 수리했다. 현재 커밋의 세 이미지 CI 결과에서 출력 미지정 경고 해소를 확인했으나 ARM64 의존성 설치 지연 경고 11줄은 남았다.

실제 로컬 frontend 기동·종료 검증은 익명 세션 계약과 PID1·PORT·종료 코드 범위다. 정상 인증된 제품 흐름, 모든 cleanup, 배포·release를 입증하지 않는다. 최신 head 승인과 필수 검사·보호 병합도 별도 확인해야 한다.

아래 Acceptance evidence 전체는 계속 유효하다. 특히 split 배포의 mail/search/calendar 실제 E2E, 개별 readiness, macOS Compose 경로, 이미지별 보안·SBOM·provenance와 보호 release의 독립 artifact 소비·복구 검증은 완료로 처리하지 않는다. 이 이슈는 OPEN으로 유지하며 PR 본문의 자동 종료 연결도 제거했다.

과거 관찰 — 2026-09-03

다음 head·Draft·검사·ruleset 설명은 당시 기록이며 현재 병합 권한의 대체 근거가 아니다.

Revalidated 2026-09-03 against protected develop@042b0c70531b229af3acbd0421a2f23098d848b3.

The repository has frontend/Dockerfile and a root multi-stage Dockerfile, and Compose already runs backend/frontend separately. The remaining release-path defect is narrower: publication/validation historically did not bind the nominal backend/frontend artifacts to explicit Docker stages, so the backend artifact could resolve to the root Dockerfile's final combined runtime.

PR #1365 is the canonical bounded remediation lane. It has now non-force adopted the current protected base at exact head 8c712639f8f754fc59f7cc31976d9324058b4e0e. The prior head was one protected commit behind; that intervening attachment-parser commit touched no #1365 path, so the branch was fast-forwarded to GitHub's ordinary two-parent merge commit rather than force-pushed/rebased. Fresh comparison against protected develop reports behind_by=0 and preserves exactly the four intended runtime-target paths: .github/workflows/docker-publish.yml, Dockerfile, frontend/Dockerfile, and backend/tests/test_runtime_image_targets.py.

The current exact head names explicit backend-runtime, frontend-runtime, and compatibility combined-runtime stages and binds PR validation/release publication to the corresponding matrix.target. The base-adoption push invalidated predecessor check/review evidence; fresh Application CI, dependency, security, Semgrep, Bandit, Docker, Scorecard, and OSV runs are queued, while absent central required-workflow results remain non-passing. #1365 is Draft until one unchanged exact head satisfies the complete live gate set.

Live merge governance

The effective gate is the intersection of active rulesets, not any one ruleset in isolation:

  • organization ruleset 18156473 (CWL Central required workflows) requires one approval, dismisses stale reviews on push, requires review-thread resolution, does not itself require last-push approval, and requires the central reusable workflows;
  • repository ruleset 17214772 (Lock default branch) requires one approval after the last push, dismisses stale reviews on push, requires review-thread resolution, strict required status checks, and exposes no repository-ruleset bypass actor;
  • therefore ordinary merge of fix(containers): publish explicit split runtime targets #1365 still requires a qualifying independent post-last-push approval plus the full exact-head required-check set. Automated/model review evidence does not substitute for that approval.

Refetch rulesets, protected tip, exact-head checks, reviews, and threads immediately before any merge action.

Target

Make frontend and backend independently deployable OCI images while preserving a supported compatibility artifact and simple Compose profile for operators who want one-command startup.

Acceptance evidence

  • backend runtime image contains backend/runtime dependencies only and does not depend on the Next.js build artifact;
  • frontend runtime image is independently buildable/runnable and reaches the backend through an explicit configured service origin;
  • release and PR-validation matrices select explicit Docker stages rather than relying on final-stage defaults;
  • health/readiness checks exist per runtime rather than only for the combined container;
  • docker compose (including the macOS profile) still provides a supported integrated deployment path;
  • authentication/session and same-origin proxy behavior remain explicit and regression-tested after the split;
  • container CI builds the exact backend/frontend targets from one exact current head, with per-image dependency/security scanning, SBOM/provenance, immutable base pins, and rollback/recovery guidance;
  • end-to-end browser/API acceptance proves mail/search/calendar flows through the split deployment;
  • the protected integrated release consumes and validates those independent artifacts before this issue closes.

Do not close this item merely because multiple Dockerfiles or explicit stages exist in an unmerged PR. Close it only after the protected integrated release path consumes and validates the independent images with all live CI/security/provenance/review/thread/workflow gates satisfied together.


Roadmap item — CWL Project #1. Phase Ops · Component naruon. Canonical platform plan: #974 (docs/planning/naruon-platform-plan.md).

Activity

  1. changed the title [-]naruon: docker frontend/backend images (verified separate)[/-] [+]naruon: split frontend and backend runtime images[/+] on Aug 14, 2026
  2. seonghobae commented on Aug 16, 2026

    @seonghobae
    ContributorAuthor

    Governance correction after a later same-day ruleset change: inherited organization ruleset 18156473 was updated at 2026-08-16T23:45:11.508+09:00 and now again requires one approving review, stale-review dismissal, approval after the last push, and review-thread resolution, in addition to its required workflows. This supersedes the earlier zero-approval snapshot recorded in the issue body. Repository ruleset 15586698 remains zero-approval but does not override the additive organization rule. #1371 is reopened for the independent-human approval path.

  3. seonghobae commented on Aug 16, 2026

    @seonghobae
    ContributorAuthor

    Fresh 2026-08-17 merge-contract correction: repository ruleset 15586698 requires zero approvals, but inherited organization ruleset 18156473 independently applies to the default branch and requires one approving review after the last push, stale-review dismissal, and resolved threads, in addition to central required workflows. Current collaborator inventory still contains only seonghobae, so #1365 remains approval-blocked and #1371 remains open. The body statement that the independent approval requirement was superseded / #1371 closed is stale.

  4. added
    area: authAuthentication, authorization, identity, or tenant isolation
    area: ci-cdCI, GitHub Actions, checks, release, or supply chain
    area: securitySecurity boundary, hardening, or vulnerability prevention
    status: triagedOpen issue has an organization taxonomy assignment
    type: featureNew or expanded product capability
    on Aug 22, 2026
  5. seonghobae commented on Sep 7, 2026

    @seonghobae
    ContributorAuthor

    자동 배포 전 남은 검증 경계

    2026-09-07 보호 develop SHA를 API로 다시 확인했습니다: 042b0c7. 이 SHA와 #1365 head 9b137f2 사이에서 .github/workflows/deploy.yml 및 두 k8s Deployment manifest의 diff는 없습니다.

    현행 deploy.yml은 VERSION으로 backend/frontend 이미지 태그를 치환하고 naruon-dev에 순차 apply한 뒤 rollout status를 기다립니다. 두 manifest에는 readinessProbe/startupProbe가 없습니다. 따라서 rollout 성공만으로 애플리케이션 준비나 실제 요청 처리를 입증할 수 없습니다. publisher는 digest를 summary에 기록하지만 deploy workflow_call에는 digest input이 없어서, 검증된 게시 artifact와 실제 소비 artifact의 동일성을 현재 계약으로 강제하지 못합니다. deploy workflow에는 명시적인 concurrency/environment 또는 실패 시 복구 절차도 없습니다. 환경 보호나 registry tag immutability가 외부에 설정됐는지는 이번 소스 조사로 판정하지 않았습니다.

    후속 구현은 게시 결과의 backend/frontend digest 전달·검증, 취소하지 않는 배포 직렬화, 실제 endpoint에 맞는 readiness, 실패 시 이전 revision 복구 및 배포 imageID/readback 확인을 기존 owner에서 묶어야 합니다. 정상 인증 사용자 흐름·실제 배포 대상 접근·수용 기준은 계속 미완료입니다. 소스 조사만 수행했으며 태그 발행, 배포 실행, credential 조회는 하지 않았습니다.

    근거: https://github.com/ContextualWisdomLab/naruon/blob/042b0c70531b229af3acbd0421a2f23098d848b3/.github/workflows/deploy.yml 및 같은 SHA의 k8s/backend-deployment.yaml, k8s/frontend-deployment.yaml. Refs #1365.

  6. seonghobae commented on Sep 7, 2026

    @seonghobae
    ContributorAuthor

    네트워크 없는 Linux 재현

    #1365 exact 9b137f25f426743e18fc61125575ec7949d45db8의 deploy.yml에서 manifest 생성 run 본문을 그대로 추출하고, 같은 SHA의 VERSION과 두 Deployment를 git archive로 전달했습니다. 기존 backend:08417ad4 로컬 이미지에서 network=none, 읽기 전용 root, capability 제거, /probe tmpfs로 실행했습니다.

    BACKEND_IMAGE_DIGEST=not-a-digest 및 빈 FRONTEND_IMAGE_DIGEST 환경을 넣어도 실제 script exit 0이며 생성 결과는 backend:0.14.4와 frontend:0.14.4였습니다. 현재 workflow가 이 환경 변수를 input으로 받는다는 뜻이 아니라, 이 단계에 digest 검증·소비 계약이 없다는 실행 반례입니다. registry/클러스터 접근은 하지 않았습니다.

    앞선 macOS 실행은 GNU sed 구문 차이로 exit 1, 첫 Linux bind-mount 실행은 Colima의 임시 경로 공유 문제로 VERSION을 찾지 못해 exit 1이었습니다. 두 결과는 계약 검증으로 세지 않았습니다. 최종 실행은 archive를 stdin으로 전달해 공유 경로 의존성을 제거했으며 임시 컨테이너는 --rm으로 종료됐습니다. 원본 worktree 변경은 없습니다.

    열린 PR 170개의 파일 목록도 페이지 끝까지 확인했습니다. deploy.yml의 다른 변경은 #1583 action pin 갱신이고, #1562의 docker-publish concurrency 변경 등은 보존할 선행 변경입니다. digest 전달 수리는 #1365 후속 stack에서 별도로 진행합니다.

  7. seonghobae commented on Sep 7, 2026

    @seonghobae
    ContributorAuthor

    직렬화 구현 전 확인한 공식 계약과 도구 불일치

    #1586 head 531eb5817e1be4ddaf190a97f0e4845b7d7ae89c는 digest 전달 수리이며 아직 배포 직렬화를 구현했다고 주장하지 않습니다. #1562의 고유 변경은 PR번호 또는 github.ref 기반 그룹입니다. 서로 다른 release tag는 서로 다른 그룹이므로 공통 배포 대상의 동시 변경을 막지 못합니다.

    현재 GitHub 공식 concurrency 문서는 queue: max를 지원합니다. cancel-in-progress: false만으로는 기존 pending 실행 교체를 막지 못하며, max도 대기 100개 초과 시 취소됩니다. 처리 순서는 그룹 대기 시작 기준이므로 tag 발행 순서를 보장하지 않습니다. 따라서 공통 대상 lock 외에도 오래된 version의 뒤늦은 배포를 거부하는 검증이 필요합니다.

    설치된 actionlint 1.7.12에 queue: max와 cancel-in-progress: false를 넣은 최소 workflow를 stdin으로 검사했더니 exit 1, unexpected key "queue" for "concurrency" section이 발생했습니다. GitHub releases API에서도 최신 release는 v1.7.12였습니다. 이 문법 불일치는 검사 무시나 queue 삭제로 덮지 않고 중앙 CI 도구 owner에 전달했습니다. 실제 workflow에 검증되지 않은 문법을 넣거나 배포를 실행하지 않았습니다.

    환경 API를 마지막 페이지까지 확인한 결과 비PR 환경은 copilot뿐이며 보호 규칙이 없습니다. naruon-dev는 현재 manifest namespace이지 보호 환경으로 확인되지 않았습니다. backend main.py의 루트 응답은 고정 status이고 DB 조회가 없으며 frontend healthcheck도 루트 HTTP 응답만 확인합니다. 이 경로를 DB readiness로 간주하지 않습니다. 환경 생성·권한 변경·클러스터 쓰기는 하지 않았습니다.

    근거: https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency ; https://github.com/rhysd/actionlint/releases/tag/v1.7.12 . 공식 문서와 실제 parser 결과를 별도로 보존합니다.

  8. seonghobae commented on Sep 7, 2026

    @seonghobae
    ContributorAuthor

    배포 대기열 검사 도구의 기존 upstream 수리 경로를 확인했습니다. rhysd/actionlint#657은 open이며 기존 PR rhysd/actionlint#654 를 연결합니다. 해당 PR은 아직 미병합(head 644076a59742c2d1540ebd4686eab3c308f0e562)이고 queue 파싱·표현식·양성/음성 fixture를 추가합니다. 최신 릴리스는 v1.7.12입니다. 새 parser를 소비자 저장소에 복제하거나 오류를 무시하지 않고 중앙 도구 담당 경로에서 기존 수리와 검증된 릴리스 채택을 이어가야 합니다. 이 조사만으로 배포 직렬화 또는 queue:max 검사 지원이 완료된 것은 아닙니다.

  9. seonghobae commented on Sep 7, 2026

    @seonghobae
    ContributorAuthor

    Release-path prerequisite update: dependent deployment stack #1586 exposed a repo-local CI trigger gap because its base is feature branch fix/publish-independent-runtime-targets, while Application CI/Bandit/Dependency Review/Docker PR triggers were restricted to long-lived bases. I opened #1587 from protected develop@042b0c70531b229af3acbd0421a2f23098d848b3 with a focused RED regression and minimal all-base ** trigger repair. Current #1587 exact head is bc83f3f11c90aef94633436b5ce78927c90211e1; Application CI and Bandit are exact-head success, CodeRabbit reviewed the exact 5-file delta with no actionable finding and submitted post-last-push approval, while Docker and central Security/Semgrep/CodeQL/opencode/dependency evidence are not yet fully terminal/present. No bypass or predecessor-evidence transfer. After #1587 normally lands, restack #1365 on the new protected head and verify #1586 actually receives repo-local exact-head workflows before treating the runtime-digest stack as mergeable.

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

    area: authAuthentication, authorization, identity, or tenant isolationarea: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: dependenciesDependency or lockfile maintenancearea: securitySecurity boundary, hardening, or vulnerability preventionenhancementNew feature or requestpriority: mediumNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmenttype: featureNew or expanded product capability

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions