거래소와 지갑의 디지털 자산 기록을 수집·정규화하고, 사용자가 검토할 수 있는 재현 가능한 장부와 보고서로 연결하는 GIWA MVP입니다.
이 저장소는 GIWA MVP의 웹 애플리케이션, Web API와 Engine을 제공합니다. apps/web의 React 화면, apps/web-api의 Fastify BFF, services/engine의 Go gRPC Source·Workflow·Query 서비스와 durable Sync worker가 구현되어 있습니다.
- Frontend: React 19, TypeScript 6, Vite 8
- Web API: Fastify 5, TypeScript, 서버 세션 기반 BFF
- Engine API: Go, protobuf, mTLS gRPC, PostgreSQL source/job/read/report stores
- Package manager: npm workspaces
- Quality: Oxlint, TypeScript, Vitest, Testing Library
- MVP 데이터 소스: Upbit 거래내역 PDF와 여러 EVM 공개 지갑 주소
전체 서비스 경계와 아직 결정되지 않은 항목은 웹 앱 기술 명세를 확인하세요. 로그인과 가입 흐름은 사용자 온보딩, 데이터 소스 등록과 날짜 설정은 데이터 소스 등록 및 수집 기간 설정, Upbit 거래의 장부 연결은 Upbit PDF Observation 정규화, DEX와 CEX를 한 연간 보고서로 구성하는 과정은 DEX·CEX 통합 세금 보고서 흐름, FINAL 보고서 결제와 다운로드 권한은 실제 보고서 x402 결제에 정리되어 있습니다. 화면의 색상·타이포·간격 기준은 웹 디자인 가이드, 저장소에서 작업을 시작하는 방법은 개발 가이드를 따릅니다.
요구 사항:
- Node.js
20.19+또는22.12+ - npm
npm install
npm run dev개발 서버는 기본적으로 http://localhost:5173에서 실행됩니다.
기능을 수정한 뒤에는 현재 체크아웃으로 Web API, Engine, PDF parser 후보 이미지를 만들고 실제 서비스 경계를 연결해 확인할 수 있습니다. Registry의 최신 기준 이미지 digest도 먼저 기록하며, DB는 실행마다 새로 만들고 종료 시 삭제합니다.
make test이 테스트는 Web API 요청에서 시작해 Engine gRPC, networkless PDF parser,
PostgreSQL source 저장까지 확인합니다. 운영 .env나 secret은 이미지에 넣지 않고
테스트 실행 중 생성되는 권한 0600 임시 환경 파일로만 전달합니다.
전체 구조와 저장소별 확인 범위는 로컬 dev E2E 실행 방법에
정리되어 있습니다.
화면을 직접 확인할 때는 자동 정리되는 make test 대신 아래 유지형 환경을 사용합니다.
make dev-e2e-up # http://localhost:15173
make dev-e2e-test # 같은 환경에서 반복 실행
make dev-e2e-status
make dev-e2e-down # 확인을 마친 뒤에만 실행고정 테스트 계정은 test@example.test / test1234!입니다. Web UI port는 Mac
Studio의 loopback에만 열리며, 개인 노트북에서는 문서의 SSH tunnel을 사용합니다.
여러 저장소를 함께 고친 경우에는 Posting candidate를 먼저 만들고, 그 이미지를 JIT와 Tax 시나리오가 이어서 사용하도록 전체 경계를 한 명령으로 확인할 수 있습니다.
make test-systemDB와 schema의 기본 경로는 각각
/Users/shared/Projects/01_Daejang/daejang-db와
/Users/shared/Projects/01_Daejang/schema로 설정되어 있습니다.
test-system은 하나의 거대한 Compose를 계속 켜 두지 않습니다. Web·Source,
Posting, JIT→Posting, Posting→Tax 시나리오를 각각 격리된 Compose network와 DB에서
순서대로 실행해, 앞 시나리오의 데이터가 다음 결과를 우연히 통과시키지 않게 합니다.
Web API는 별도 터미널에서 실행합니다.
npm run dev:apiWeb API의 기본 주소는 http://127.0.0.1:3000입니다. 설정 가능한 환경 변수는 apps/web-api/.env.example에서 확인할 수 있습니다.
실제 지갑 source를 로컬 DB에 저장하려면 daejang-db migration과 Source Engine도
실행해야 합니다. 로컬 plaintext gRPC는 loopback에만 명시적으로 허용되며 자세한
설정은 services/engine/README.md를 따릅니다.
운영 DB에는 Web API를 시작하기 전에 daejang-db의 중앙 migration을 적용합니다.
cd ../daejang-db
DATABASE_URL='postgresql://...' make migrate-upWeb API는 다음 보안 경계를 기본으로 적용합니다.
- opaque host-only Session cookie와 절대·유휴 만료
- 상태 변경
/api/*요청의 Origin·Fetch Metadata 검증 - API 응답 cache 금지, 보안 헤더와 민감 로그 redaction
- 서버 Session에서 확인한 단일 사용자 UUID만 신뢰
- PostgreSQL SessionStore와 사용자 상태·session epoch 기반 즉시 Session 무효화
- 버전별 이용약관·개인정보 처리방침과 append-only 사용자 동의 이력
- 공급자별 PostgreSQL 로그인 rate limit과 Session Token 회전
- Engine private gRPC client certificate mTLS preflight
- 서버 Session 기반 Source·Workflow·Query 호출과 503/504 오류 변환
- private Upbit PDF 업로드, digest 검증, durable Sync Job lease
- 실제 DB 기반 Dashboard·Activity·Ledger·Review와 immutable Report snapshot
메모리 SessionStore와 rate-limit store는 로컬 개발과 테스트 전용입니다. 운영 모드는 DATABASE_URL, 32 byte 이상의 RATE_LIMIT_HMAC_SECRET, Engine CA·client certificate·private key 설정이 없으면 시작하지 않습니다. Web schema는 daejang-db migration이 소유하며 OAuth·이메일 인증 persistence는 000015에서 추가됩니다. 현재 Web API는 wallet ownership 경계까지 반영된 web-auth-persistence v2 / migration 11 계약을 요구합니다. ingress 기준은 deploy/nginx, DB부터 Worker까지 실제 배포 순서는 계정 인증 배포 실행 순서에 있습니다.
Migration 62가 적용된 DB에서는 인증 Session의 사용자 ID를 subject 경계로 사용해 현재
신고서 read model을 조회합니다. 요청 header나 query로 다른 subject를 지정할 수 없으며,
금액 상태가 UNKNOWN이면 amount를 0으로 만들지 않고 필드 자체를 생략합니다.
GET /api/v1/tax-reports/:taxYear/current?finality=FINAL|PROVISIONAL&residentId=...
GET /api/v1/tax-reports/:reportId
GET /api/v1/tax-reports/:reportId/artifacts/pdf
서버는 시작 시 읽기 권한이 필요한 reporting.tax_report,
reporting.current_tax_report와 tax-report-persistence migration 62 계약만
확인합니다. 세금 계산 상세 테이블은 Web API 역할에 노출하지 않습니다.
두 번째 경로는 Tax Engine이 발행한 exact ReportModelV1을 subject 범위와
artifact digest까지 확인한 뒤 사용자용 상세 장부로 투영합니다. 세 번째 경로는
같은 reportId로 한글 PDF를 즉시 생성합니다. UNKNOWN 금액은 두 출력 모두
0이 아니라 미확정으로 유지하고, PDF에는 EAS transaction·UID나 x402 상태를
포함하지 않습니다.
로컬에서 상세 장부와 PDF까지 확인하려면 Tax Engine과 같은 artifact database 및
filesystem을 Engine API에 연결해야 합니다. 통합 host runtime을 이미 provision한
환경은 npm run backend:start를 사용합니다. 수동 개발 runtime은
./scripts/dev-local.sh --help에 나온 DB 환경 변수와 함께
GIWA_TAX_ARTIFACT_DATABASE_URL, GIWA_TAX_ARTIFACT_BASE를 설정한 뒤 아래처럼
실행합니다.
./scripts/dev-local.sh --with-enginenpm run lint
npm run typecheck
npm test
npm run buildapps/
web/ React 웹 애플리케이션
web-api/ Fastify Web API / BFF
proto/ Web API와 Engine의 canonical gRPC 계약
services/
engine/ Go SourceService API
docs/ 제품 흐름과 웹 기술 명세
DB migration과 persistence client는 daejang-db가 소유합니다. Engine 실행 방법은 services/engine/README.md, 남은 연동 순서는 Engine 연동 구현 현황과 계획을 확인하세요.
- 대장 Flow
- Technical Spec — GIWA MVP v0.1
- 인증·Session Sequence
- 실제 보고서 x402 결제 Sequence
- Mac Studio 개발·배포 가이드
- 버그, 기능 요청, 작업 제안은 GitHub Issues에 등록합니다.
- 작업 브랜치는 동기화된 Linear 이슈의 Copy git branch name으로 생성합니다.
- 변경 사항은 Pull Request로 제출합니다.
- 코딩 에이전트는 AGENTS.md의 공통 지침을 따릅니다. Claude Code는 CLAUDE.md를 통해 같은 지침을 불러옵니다.
- 기여 방법은 CONTRIBUTING.md를 확인하세요.
- 이슈부터 branch, 검증, PR과 병합까지의 실제 순서는 개발 가이드를 확인하세요.
이 저장소를 GitHub 템플릿으로 생성했다면 TEMPLATE_SETUP.md의 체크리스트를 먼저 완료하세요.