- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환 - Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용 - pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관) - worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md) - D:\Rhino-MCP 경로 참조를 새 위치로 치환 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
67 lines
3.6 KiB
Python
67 lines
3.6 KiB
Python
"""Create an owner-authorized private deployment archive outside the repository.
|
|
|
|
The archive contains credentials. Never commit it or expose it via the app.
|
|
"""
|
|
import argparse
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import sys
|
|
import zipfile
|
|
|
|
ROOT=Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0,str(ROOT/'deployment'))
|
|
from install_ai_auth import parse_auth
|
|
|
|
|
|
def package(auth, gitea_archive, output):
|
|
output=output.resolve()
|
|
if output==ROOT or ROOT in output.parents:
|
|
raise ValueError('Private login archive must be outside the repository')
|
|
payload=auth.read_bytes();parse_auth(payload)
|
|
with zipfile.ZipFile(gitea_archive) as existing:
|
|
names=[n for n in existing.namelist() if Path(n).name=='gitea-token.txt']
|
|
if len(names)!=1:raise ValueError('One private Gitea token file is required')
|
|
token=existing.read(names[0])
|
|
if not token.strip() or len(token)>16384:raise ValueError('Invalid Gitea credential file')
|
|
output.parent.mkdir(mode=0o700,parents=True,exist_ok=True)
|
|
if output.parent.stat().st_mode & 0o077:
|
|
raise ValueError('Use an owner-only output directory (mode 700)')
|
|
fd=os.open(output,os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600)
|
|
instructions='''비공개 서버 배포 묶음 — 로그인 정보 포함
|
|
|
|
이 ZIP은 비밀번호와 동일하게 취급하십시오. Gitea·공유 게시판에 올리지 마십시오.
|
|
승인된 배포 서버 10.14.12.22에만 안전한 방법으로 전달하십시오.
|
|
|
|
1. 서버의 비공개 폴더에 ZIP 전체를 풉니다. 세 파일을 같은 폴더에 둡니다.
|
|
2. Git, PowerShell, Docker Linux 컨테이너와 기존 Caddy 관리 API가 준비돼 있어야 합니다.
|
|
3. deploy-server.bat를 실행합니다. 코드·7개 저장 모델은 Gitea에서 내려받습니다.
|
|
4. codex-auth.json은 컨테이너 이미지가 아닌 전용 인증 볼륨에 전달합니다.
|
|
5. 로그인 상태 검사와 서비스 경로 검사가 성공하면 다음 주소를 엽니다.
|
|
http://10.14.12.22/box-sample/
|
|
|
|
접속 PC에는 로그인 파일을 배포하지 않습니다. AI 요청은 서버 계정에서 실행됩니다.
|
|
AI 사용량은 이 계정에서 소모됩니다. 승인된 사내 접속자에게만 서비스를 허용하십시오.
|
|
계정 로그아웃·인증 취소·만료·네트워크 제한이 발생하면 재인증이 필요할 수 있습니다.
|
|
서버가 갱신한 인증은 재배포해도 보존하며 오래된 이 파일로 덮어쓰지 않습니다.
|
|
로그인 상태 통과는 실제 도면 생성 완료를 뜻하지 않습니다.
|
|
원격 배포 서버에서의 최종 실행은 아직 검증하지 않았습니다.
|
|
'''
|
|
with os.fdopen(fd,'wb') as stream,zipfile.ZipFile(stream,'w',compression=zipfile.ZIP_DEFLATED) as archive:
|
|
launcher=(ROOT/'deploy-server.bat').read_text().replace('\r\n','\n').replace('\n','\r\n')
|
|
archive.writestr('deploy-server.bat',launcher)
|
|
archive.writestr('gitea-token.txt',token)
|
|
archive.writestr('codex-auth.json',payload)
|
|
archive.writestr('먼저읽기.txt',instructions)
|
|
# Only the artifact location and generic state are reported, never secrets.
|
|
return {'archive':str(output),'contains_private_credentials':True,'mode':'0600'}
|
|
|
|
|
|
if __name__=='__main__':
|
|
parser=argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--auth',required=True,type=Path)
|
|
parser.add_argument('--gitea-archive',required=True,type=Path)
|
|
parser.add_argument('--output',required=True,type=Path)
|
|
args=parser.parse_args()
|
|
print(json.dumps(package(args.auth,args.gitea_archive,args.output),ensure_ascii=False))
|