Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions docs/acquisition-data-room-integrity.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,19 @@ Manifest와 integrity 단계가 별도 경로를 추측하지 않도록 `NOEMA_D
`source.commitSha`는 단순한 `git rev-parse HEAD` 기록이 아니다. Manifest generator와 integrity audit는 catalog/verifier를 읽기 전에 `scripts/lib/acquisition-git-preflight.mjs`로 tracked checkout을 인증한다.

1. `HEAD^{commit}`을 local Git object database에서 exact 40-character SHA-1 또는 64-character SHA-256 commit으로 해석한다.
2. system/global Git configuration, hooks, filesystem monitor, untracked cache, replacement objects, lazy fetch, terminal prompt를 비활성화하고 필요한 process-discovery 환경만 전달한다. 격리된 config에서도 CI checkout의 dubious-ownership 보호를 우회하지 않고 정확히 현재 command `cwd`만 command-scope `safe.directory`로 허용한다. 같은 exact `cwd`를 `GIT_WORK_TREE`에도 고정하여 repository-local `core.worktree`가 Git의 tracked-byte 비교를 다른 디렉터리로 redirect하지 못하게 한다.
3. `git ls-files -v -z --cached --`의 전체 NUL-delimited 결과를 최대 2 MiB로 bounded read하고, `S`로 표시되는 `skip-worktree` 또는 lowercase tag로 표시되는 `assume-unchanged` entry가 하나라도 있으면 tracked-byte 비교 전에 실패한다. 이 index hint들은 정상적인 working-tree 검사를 생략하게 할 수 있으므로 acquisition checkout에서는 허용하지 않는다.
4. `git diff --cached --quiet --no-ext-diff --no-textconv --ignore-submodules=none <exact-head> --`로 index의 staged content/mode가 exact commit과 같은지 확인한다. `--cached` 비교는 on-disk worktree를 고려하지 않으므로 repository-configured clean filter가 이 단계의 source identity를 바꿀 수 없다.
5. `git diff-files --quiet --no-ext-diff --no-textconv --ignore-submodules=none --`로 실제 worktree와 이미 인증된 index 사이의 tracked drift를 확인한다. 이 low-level index/worktree 비교를 사용하여 일반 `git diff <commit>`의 check-in conversion 경로가 repository-local `filter.<driver>.clean` command를 실행하거나 그 출력으로 tampering을 숨기는 것을 방지한다.
6. 같은 bounded index inspection을 다시 실행해 comparison 도중 unsafe index hint가 생기지 않았는지 확인한다.
7. `HEAD^{commit}`을 다시 해석해 preflight 도중 branch movement를 거부한다.
8. verifier/catalog module은 이 preflight가 성공한 뒤에만 dynamic import한다.
9. retained evidence를 모두 읽은 뒤 같은 exact SHA를 기대값으로 tracked checkout 전체 절차를 다시 인증하고, source movement·tracked mutation·unsafe index hint가 있으면 output을 성공 evidence로 기록하지 않는다.
2. system/global Git configuration, hooks, filesystem monitor, untracked cache, replacement objects, lazy fetch, terminal prompt를 비활성화하고 필요한 process-discovery 환경만 전달한다. 격리된 config에서도 CI checkout의 dubious-ownership 보호를 우회하지 않고 정확히 현재 command `cwd`만 command-scope `safe.directory`로 허용한다. 같은 exact `cwd`를 `GIT_WORK_TREE`에도 고정하여 repository-local `core.worktree`가 Git의 tracked-byte 확인을 다른 디렉터리로 redirect하지 못하게 한다.
3. `git ls-files -v -z --cached --`의 전체 NUL-delimited 결과를 최대 2 MiB로 bounded read하고, `S`로 표시되는 `skip-worktree` 또는 lowercase tag로 표시되는 `assume-unchanged` entry가 하나라도 있으면 실패한다.
4. `git diff --cached --quiet --no-ext-diff --no-textconv --ignore-submodules=none <exact-head> --`로 staged index의 content/mode가 exact commit과 같은지 확인한다. 이 단계는 on-disk worktree를 읽지 않으므로 repository-configured clean/process filter를 source-identity helper로 실행하지 않는다.
5. 이미 고정한 exact HEAD를 `git ls-tree -r --full-tree -z <exact-head> --`로 읽어 immutable commit-tree의 mode, object ID, path inventory를 만든다. Mutable index object ID는 raw-byte authority로 사용하지 않는다.
6. exact-tree의 `100644`와 `100755` regular-file entry만 허용한다. 각 path를 `lstat`한 뒤 `O_RDONLY | O_NOFOLLOW` descriptor로 열고, path/descriptor의 device, inode, mode, size, modification/change time을 pre/post read에서 비교한다. Exact-tree executable mode도 filesystem mode와 별도로 검증한다.
7. descriptor size를 기준으로 bounded read한 실제 bytes에 Git의 `blob <size>\0<bytes>` framing을 적용하고 Node 표준 `crypto`의 SHA-1 또는 SHA-256으로 object ID를 계산해 exact HEAD tree object ID와 exact-match한다. Worktree-aware `git diff-files`, 파일별 `git hash-object` subprocess, 두 번째 pathname open은 source-byte authority에 사용하지 않는다.
8. 같은 bounded index-hint inspection을 다시 실행하고 `HEAD^{commit}`을 다시 해석해 preflight 도중 unsafe hint나 branch movement를 거부한다.
9. verifier/catalog module은 이 preflight가 성공한 뒤에만 dynamic import한다.
10. retained evidence를 모두 읽은 뒤 같은 exact SHA를 기대값으로 tracked checkout 전체 절차를 다시 인증하고, source movement·tracked mutation·unsafe index hint가 있으면 output을 성공 evidence로 기록하지 않는다.

비교는 **의도적으로 untracked 파일을 dirty source로 취급하지 않는다.** 실제 KPI, deployment receipt, revenue/transfer evidence 같은 acquisition artifact는 checkout에 보존될 수 있지만 source commit 자체의 일부라고 주장하지 않는다. 반대로 tracked README, policy, verifier, catalog, test, documentation 또는 control file이 HEAD와 다르거나 `skip-worktree`/`assume-unchanged`로 실제 working-tree 비교에서 숨겨지면 동일한 `source.commitSha`를 붙여 readiness evidence를 만들 수 없다. Repository-local clean/smudge filter는 정상 개발 workflow에서는 유효한 Git 기능이지만 acquisition preflight의 authorization helper로 실행되거나 그 transformed output이 raw checkout identity를 대신하도록 허용하지 않는다.
검증은 **의도적으로 untracked 파일을 dirty source로 취급하지 않는다.** 실제 KPI, deployment receipt, revenue/transfer evidence 같은 acquisition artifact는 checkout에 보존될 수 있지만 source commit 자체의 일부라고 주장하지 않는다. 반대로 tracked README, policy, verifier, catalog, test, documentation 또는 control file의 descriptor bytes가 exact HEAD tree와 다르거나 `skip-worktree`/`assume-unchanged`가 설정되어 있으면 동일한 `source.commitSha`를 붙여 readiness evidence를 만들 수 없다. Repository-local clean/smudge/process filter는 정상 개발 workflow에서는 유효한 Git 기능이지만 acquisition preflight의 authorization helper로 실행되거나 그 transformed output이 raw checkout identity를 대신하도록 허용하지 않는다.

Preflight Git 명령은 network fetch를 하지 않으며 `GIT_NO_LAZY_FETCH=1`을 사용한다. 이 경계의 bootstrap trust root는 trusted CI/checkout provisioner가 실행한 Node.js runtime, Git executable/local object database, 두 acquisition entrypoint, 작은 Git preflight module, 그리고 descriptor-safe private-output helper다. 이 코드는 실행 전에 자기 자신을 cryptographically self-authenticate한다고 주장하지 않는다. Bootstrap 자체의 무결성은 protected exact source checkout과 기존 CI/release provenance plane이 담당하고, 이 preflight는 그 이후 current working tree가 exact commit에서 drift하거나 unsafe index hint, repository-local worktree redirection, 또는 repository-configured clean filter로 drift를 숨기는 문제를 차단한다.
Preflight Git 명령은 network fetch를 하지 않으며 `GIT_NO_LAZY_FETCH=1`을 사용한다. 이 경계의 bootstrap trust root는 trusted CI/checkout provisioner가 실행한 Node.js runtime, Git executable/local object database, 두 acquisition entrypoint, 작은 Git preflight module, 그리고 descriptor-safe private-output helper다. 이 코드는 실행 전에 자기 자신을 cryptographically self-authenticate한다고 주장하지 않는다. Bootstrap 자체의 무결성은 protected exact source checkout과 기존 CI/release provenance plane이 담당하고, 이 preflight는 그 이후 current working tree가 exact commit에서 drift하거나 unsafe index hint, repository-local worktree redirection, 또는 repository-configured conversion helper로 byte authentication 전에 code execution이 발생하는 문제를 차단한다.

## Local evidence verification

Expand Down Expand Up @@ -143,4 +144,4 @@ Integrity failure를 해결하기 위해 다음을 해서는 안 된다.
- branch protection, independent approval, security gate 우회
- self-modifying/repair GitHub Actions 추가

Tracked source를 exact commit으로 복구하고 unsafe index hint를 제거한 뒤 evidence를 다시 수집하거나 올바른 retained artifact를 복구한다. 안전하지 않은 output leaf 또는 parent path가 있으면 해당 filesystem object를 별도의 trusted 운영 절차로 제거·격리한 다음 새 exact checkout에서 다시 생성한다. 그 다음 `npm run acquisition:manifest`를 새 exact checkout에서 다시 생성하고 `npm run acquisition:integrity`를 실행한다.
Tracked source를 exact commit으로 복구하고 unsafe index hint를 제거한 뒤 evidence를 다시 수집하거나 올바른 retained artifact를 복구한다. 안전하지 않은 output leaf 또는 parent path가 있으면 해당 filesystem object를 별도의 trusted 운영 절차로 제거·격리한 다음 새 exact checkout에서 다시 생성한다. 그 다음 `npm run acquisition:manifest`를 새 exact checkout에서 다시 생성하고 `npm run acquisition:integrity`를 실행한다.
41 changes: 21 additions & 20 deletions docs/acquisition-git-content-authentication.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
# Acquisition Git Content Authentication

Noema의 buyer data-room 검증은 `git diff-files`가 clean이라고 보고한 사실만으로 tracked checkout의 실제 bytes가 exact commit과 같다고 승인하지 않는다. Git index는 성능을 위해 파일의 cached stat metadata를 저장하며, timestamp와 size 조건에 따라 내용이 바뀌어도 stat tuple이 같아 보이는 “racily clean” 상태가 발생할 수 있다. 또한 index 자체는 mutable state이므로 raw-byte authority의 expected blob identity도 index에서 가져오지 않는다.
Noema의 buyer data-room 검증은 worktree-aware Git 비교를 tracked checkout의 byte authority로 사용하지 않는다. `git diff-files` 같은 경로는 repository-local `.gitattributes`가 선언한 clean/process conversion helper를 실행할 수 있고, Git index는 성능을 위해 cached stat metadata를 사용하므로 same-size·same-timestamp 변조를 실제 bytes와 독립적으로 인증하지 못한다. Index 자체도 mutable state이므로 raw-byte authority의 expected blob identity는 index가 아니라 처음 고정한 exact commit tree에서만 가져온다.

## Required verification sequence

Acquisition manifest 생성과 integrity audit는 다음 검사를 모두 통과해야 한다.

1. exact `HEAD^{commit}`을 local object database에서 40자리 SHA로 해석한다.
1. exact `HEAD^{commit}`을 local object database에서 40자리 SHA-1 또는 64자리 SHA-256 commit으로 해석한다.
2. `skip-worktree`와 `assume-unchanged` index hint를 bounded NUL-delimited inspection으로 거부한다.
3. staged index가 exact HEAD와 같은지 `git diff --cached`로 확인한다.
4. ordinary worktree drift를 `git diff-files`로 확인한다. 이 단계는 빠른 defense in depth이며 최종 byte authority가 아니다.
5. 이미 인증한 exact HEAD를 `git ls-tree -r --full-tree -z`로 읽어 immutable commit-tree의 mode, object ID, path inventory를 만든다. 출력은 parser가 요구하는 bounded NUL-delimited mode/object/stage-shaped record로 formatting하며 mutable index object ID를 authority로 사용하지 않는다.
6. exact-tree의 `100644` 또는 `100755` regular-file entry만 허용한다. Symlink, gitlink, sparse-directory mode 등 지원하지 않는 object mode는 fail-closed다.
7. 각 path를 `lstat`한 뒤 `O_RDONLY | O_NOFOLLOW` descriptor로 열고, path와 descriptor의 device, inode, mode, size, modification time, change time이 일치해야 한다.
8. exact-tree executable mode와 descriptor의 owner-execute bit를 독립적으로 비교한다.
9. descriptor size를 기준으로 `size + 1` bounded buffer를 할당하고 descriptor에서 직접 읽는다. Short read, growth 또는 invalid read count를 거부한다.
10. read 후 descriptor와 path identity를 다시 비교한다.
11. descriptor에서 읽은 exact bytes를 `git hash-object --stdin`으로 계산하고 exact HEAD tree object ID와 정확히 비교한다.
12. index hint와 exact HEAD를 다시 확인한다.

이 순서는 staged-index 비교가 끝난 직후 다른 local writer가 index를 다시 써도 raw-byte authority가 새 index object ID로 바뀌지 않게 한다. Expected blob identity는 처음 고정한 exact HEAD commit tree에서만 파생된다. Pathname을 두 번째로 다시 열어 hash하지 않으므로 검증 전 path와 hash 대상 사이의 교체 경로도 줄인다. Tracked symbolic link는 현재 descriptor-bound link-target read가 제공되지 않으므로 허용 가능한 source mode로 취급하지 않는다.
3. staged index가 exact HEAD와 같은지 `git diff --cached`로 확인한다. 이 비교는 worktree를 읽지 않으므로 repository-local clean/process filter를 source-identity helper로 실행하지 않는다.
4. 이미 인증한 exact HEAD를 `git ls-tree -r --full-tree -z`로 읽어 immutable commit-tree의 mode, object ID, path inventory를 만든다. Mutable index object ID는 raw-byte authority로 사용하지 않는다.
5. exact-tree의 `100644` 또는 `100755` regular-file entry만 허용한다. Symlink, gitlink, sparse-directory mode 등 지원하지 않는 object mode는 fail-closed다.
6. 각 path를 `lstat`한 뒤 `O_RDONLY | O_NOFOLLOW` descriptor로 열고, path와 descriptor의 device, inode, mode, size, modification time, change time이 일치해야 한다.
7. exact-tree executable mode와 descriptor의 owner-execute bit를 독립적으로 비교한다.
8. descriptor size를 기준으로 `size + 1` bounded buffer를 할당하고 descriptor에서 직접 읽는다. Short read, growth 또는 invalid read count를 거부한다.
9. read 후 descriptor와 path identity를 다시 비교한다.
10. descriptor에서 읽은 exact bytes에 Git의 `blob <size>\0<bytes>` framing을 적용해 Node 표준 `crypto`의 SHA-1 또는 SHA-256으로 object ID를 계산하고 exact HEAD tree object ID와 정확히 비교한다. 파일별 `git hash-object` subprocess나 pathname 재개방은 사용하지 않는다.
11. index hint와 exact HEAD를 다시 확인한다.

이 순서는 staged-index 비교가 끝난 직후 다른 local writer가 index를 다시 써도 raw-byte authority가 새 index object ID로 바뀌지 않게 한다. Expected blob identity는 처음 고정한 exact HEAD commit tree에서만 파생된다. 또한 worktree-aware `git diff-files`를 preflight에 넣지 않으므로 repository attributes가 등록한 executable clean/process helper를 checkout 인증 전에 실행하지 않는다. Pathname을 두 번째로 다시 열어 hash하지 않으므로 검증 전 path와 hash 대상 사이의 교체 경로도 줄인다. Tracked symbolic link는 현재 descriptor-bound link-target read가 제공되지 않으므로 허용 가능한 source mode로 취급하지 않는다.

## Bounded work

Expand All @@ -35,11 +34,11 @@ Raw authentication은 다음 상한을 적용한다.

Per-file 및 aggregate byte budget은 해당 descriptor read와 blob hash를 시작하기 전에 확인된다. 따라서 oversized checkout을 읽은 뒤 뒤늦게 거부하지 않는다.

## Why exact-tree descriptor-bound stdin hashing is used
## Why exact-tree descriptor-bound local hashing is used

Acquisition source identity는 checkout의 실제 bytes를 특정 immutable commit에 결박해야 한다. `.gitattributes`의 clean filter, end-of-line conversion, pathname 재해석, repository-local helper뿐 아니라 cached stat 또는 concurrently rewritten index도 current filesystem bytes의 expected identity를 대신할 수 없다.
Acquisition source identity는 checkout의 실제 bytes를 특정 immutable commit에 결박해야 한다. `.gitattributes`의 clean/process filter, end-of-line conversion, pathname 재해석, repository-local helper뿐 아니라 cached stat 또는 concurrently rewritten index도 current filesystem bytes의 expected identity를 대신할 수 없다.

Noema는 먼저 고정된 commit의 tree object IDs를 `git ls-tree`로 읽고, `O_NOFOLLOW` descriptor로 인증한 regular file bytes만 읽어 그 buffer를 `git hash-object --stdin`에 전달한다. Git은 standard input을 blob contents로 hash하므로 pathname filter나 두 번째 path open에 의존하지 않는다. Hash 전후 descriptor/path identity와 executable mode는 blob contents와 별도로 검증한다.
Noema는 먼저 고정된 commit의 tree object IDs를 `git ls-tree`로 읽고, `O_NOFOLLOW` descriptor로 인증한 regular file bytes만 읽는다.exact buffer를 Git blob framing으로 직접 SHA-1/SHA-256 해시하므로 worktree-aware Git conversion, 파일별 subprocess, 두 번째 pathname open에 의존하지 않는다. Hash 전후 descriptor/path identity와 executable mode는 blob contents와 별도로 검증한다.

## Failure policy

Expand Down Expand Up @@ -73,7 +72,7 @@ Noema는 먼저 고정된 commit의 tree object IDs를 `git ls-tree`로 읽고,

## Operational response

`tracked checkout differs from its authenticated Git index bytes`, exact-tree mismatch 또는 descriptor-bound verification failure가 발생하면 다음 순서로 복구한다.
`tracked checkout differs from exact HEAD tree bytes`, exact-tree mismatch 또는 descriptor-bound verification failure가 발생하면 다음 순서로 복구한다.

1. 현재 process가 보고한 source SHA를 승인하지 않는다.
2. tracked file과 index state를 신뢰된 checkout에서 복구한다.
Expand All @@ -83,12 +82,14 @@ Noema는 먼저 고정된 commit의 tree object IDs를 `git ls-tree`로 읽고,

## References

Git Project. (2026). *Git documentation: git-hash-object*. https://git-scm.com/docs/git-hash-object

Git Project. (2026). *Git documentation: git-ls-tree*. https://git-scm.com/docs/git-ls-tree

Git Project. (2026). *Git documentation: git-ls-files*. https://git-scm.com/docs/git-ls-files

Git Project. (2026). *Git object database*. https://git-scm.com/book/en/v2/Git-Internals-Git-Objects

Git Project. (2026). *Racy Git*. https://git-scm.com/docs/racy-git.html

OpenJS Foundation. (2026). *Crypto*. Node.js documentation. https://nodejs.org/api/crypto.html

OpenJS Foundation. (2026). *File system*. Node.js documentation. https://nodejs.org/api/fs.html
Loading
Loading