어제 검증한 프로그램의 제목이 오늘도 같다고 같은 코드인 것은 아니다. Python 한 줄이나 노트북 셀이 바뀌었어도 예전 완료 표시가 남을 수 있다. 나는 검증 표시가 프로그램 이름에 붙는 것이 아니라 실제 확인한 정의의 내용에 붙어야 한다고 보고 실행 전 파일을 다시 비교하게 했다.
비교 대상은 세 파일의 역할에 맞춰 정한다
ProgramLibrary.hash는 recipe.json과 workflow.py의 바이트를 읽고 inspect.ipynb의 셀 종류와 source를 이어 해시한다. 실행할 정의와 Python 진입점, 노트북 실행 소스를 함께 묶는다. 한 파일만 확인하면 다른 형식의 실행 내용이 바뀌어도 과거 검증을 계속 붙일 수 있다.
노트북 전체 파일을 그대로 해시하지는 않는다. 출력과 실행 횟수 같은 실행 후 변화가 아니라 셀의 소스 구성을 비교한다. 이것은 노트북의 모든 metadata가 중요하지 않다는 일반 규칙이 아니다. 현재 구현에서 실행 정의로 취급한 범위를 정한 것이다. 어떤 내용을 제외하는지도 검증 계약의 일부다.
목록 표시와 실행 거절을 서로 이어 준다
목록을 만들 때 현재 hash와 manifest의 hash가 다르면 코드 변경·재검증 필요 상태를 표시한다. 실제 load도 같은 비교를 하고 PROGRAM_CHANGED로 거절한다. 화면만 경고하고 실행에서는 그대로 허용하는 식으로 두 경계가 갈라지지 않게 한다.
자동 검색은 load에 실패한 변경 프로그램을 후보에서 제외하는 경로를 가진다. 기존 이름이 검색에 잘 맞아도 변경된 정의를 조용히 선택하지 않는 것이다. 나는 경고 문구보다 실제 실행 경계가 더 중요하다고 봤다. 사람이 그 문구를 못 봤거나 에이전트가 목록 일부만 읽어도 거절 규칙은 남아 있어야 한다.
절차를 찾는 hash와 실행 무결성 hash는 다르다
recipeIdentity는 같은 절차를 중복 등록하지 않도록 이름과 보통의 입력 기본값을 정리해 비교한다. 실행 무결성 hash는 실제 파일 내용을 비교한다. 이름과 기본값이 달라도 재사용 후보가 될 수 있다는 것과 바뀐 Python 파일을 검증 없이 실행해도 된다는 것은 다른 결론이다.
나는 이 두 값을 모두 hash라고 부른다는 이유로 같은 기능처럼 설명하지 않는다. 하나는 어떤 절차인지 찾는 구조 비교이고 다른 하나는 확인한 파일 그대로인지 묻는 비교다. 예상하는 변경이 다르므로 시험과 실패 상태도 달라진다. 중복 보관을 줄이는 규칙이 검증을 약하게 만들어서는 안 된다.
정상 실행도 변경된 파일에 완료 표시를 남기지 않는다
실행이 끝난 뒤 manifest 상태를 갱신하는 경로도 현재 library.hash가 실행 당시 hash와 같은지 확인한다. 실행 중 파일이 바뀌었다면 새 파일에 과거 실행 성공을 그대로 붙이지 않으려는 조건이다. 예약은 별도로 생성 당시 hash를 저장해 실행 직전에 다시 비교한다.
이 검사가 모든 동시 파일 변경을 완벽히 차단하는 파일 잠금은 아니다. 비교 뒤 실행까지의 모든 경쟁이나 악의적인 같은 프로세스 변경을 해결했다고 주장하지 않는다. 내용 확인 시점과 결과 표시의 결합을 강화한 경계다. 더 강한 배포 요구에는 불변 패키지나 실행 사본 같은 추가 설계가 필요할 수 있다.
시험은 한쪽만 바꾸고 다른 사본을 함께 본다
기존 보관함 시험은 두 정의를 저장한 뒤 한쪽 workflow.py에 내용을 추가한다. 바꾼 쪽 load는 실패해야 하고 다른 사본은 원래 이름으로 정상 읽혀야 한다. 프로젝트 정의 시험은 한쪽 recipe를 바꿔도 이웃과 공통 목록의 바이트가 남는지 함께 확인한다.
이 글의 근거는 실제 구현과 기존 시험 코드이며 원래 앱을 새로 실행한 결과가 아니다. 홈페이지의 독립 합성 모듈은 원본 런타임과 별개로 시험하고 ZIP 해시를 대조한다. 두 검사를 합쳐 모든 배포 환경의 코드 검증이 끝났다고 말하지 않는다. 어느 파일과 시점을 확인했는지 남겨야 한다.
hash가 같아도 업무가 맞는지는 다시 묻는다
같은 바이트라는 것은 코드가 확인 당시와 같다는 뜻이다. 사이트가 바뀌지 않았다는 보장도, 입력이 맞다는 판단도, 현재 사용자가 실행을 허락했다는 증거도 아니다. 나는 hash를 만능 안전 표시로 사용하지 않는다. 무결성은 실행할 때 확인할 여러 조건 중 하나다.
프로그램을 고친 다음에는 어떤 부분이 바뀌었는지 읽고 필요한 재검증을 해야 한다. 완료 표시만 되살리려고 manifest의 hash를 수동으로 맞추는 것은 이 질문을 건너뛴다. 제작자로서 남기고 싶은 것은 초록색 표시가 아니라 그 표시가 어느 정의와 어떤 확인을 근거로 하는지 설명할 수 있는 구조다.