콘텐츠로 이동

Station 과 OS

Station 은 사용자의 환경이고, OS 는 Station 에 하나씩 딸린 운영 상태예요. Station 을 만들면 OS 가 함께 생겨요. Station 은 프로젝트에 속하고, 크레딧은 내 계정에 있어요.

터미널 창
curl -s -X POST $OS/api/v1/stations -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"name":"lab","description":"실험실"}'
  • project_id 를 주면 그 프로젝트에 만들어요 (없거나 남의 것이면 404 PROJECT_NOT_FOUND). 없으면 가장 오래된 프로젝트에, 프로젝트가 하나도 없으면 “기본 프로젝트” 를 만들어 넣어요.
  • GET /stations 는 모든 프로젝트의 내 Station 이에요. 프로젝트별은 GET /projects/{id}/stations.
  • GET /stations/{id}/overview — Station·OS·기기 요약·Dock 을 한 번에. 데스크톱 화면은 이것 하나로 처음을 그려요.
  • GET /stations/{id}/usage — 기기·virtual Device·Storage·저장 객체의 사용량과 한도. 크레딧 사용량은 아래 크레딧.
  • GET /stations/{id}/metrics ?from=&to=&bucket=hour|day — 명령 수·성공·실패·지연(p50·p95)의 시계열과 명령별·기기별·오류별 집계. 명령 기록을 그때그때 집계해요 — 지표를 따로 저장하거나 주기적으로 모으지 않아요. 기본은 최근 24시간·hour, 범위는 31일까지예요.
  • GET /stations/{id}/objects/tree ?prefix= — 저장 객체 이름의 / 를 폴더로 보아 한 층을 돌려줘요 (그 층의 폴더와 개수·크기, 객체). 폴더를 따로 만들지 않아요 — 이름 규칙뿐이에요. 기기 안의 파일은 명령(list_dir 등)으로 봐요.

PATCH /stations/{id}/os 로 바꿔요. 준 키만 바뀌어요.

설정 뜻 기본
max_resources 기기 수 한도 (actual·virtual 합계, 1~500) 50
allowed_kinds 허용할 기기 kind (actual·virtual 모두) 전부
max_virtual_devices virtual Device 수 한도 (0~50). 0 이면 클라우드에 만들 수 없어요 10
max_volume_gb virtual Device 영구 볼륨(Storage) 합계 한도 (0~2000) 100
default_command_timeout_ms 명령의 기본 실행 예산 (1000~120000) 12000

한도를 넘으면 409 (DEVICE_LIMIT_REACHED·VIRTUAL_DEVICE_LIMIT_REACHED·VOLUME_QUOTA_EXCEEDED), 허용하지 않은 kind 는 422 DEVICE_KIND_NOT_ALLOWED. 동시에 만들어도 넘지 않아요 — 한도 판정과 생성이 한 트랜잭션이에요. max_virtual_devices 를 지금 수보다 줄이면 새로 만드는 것만 막혀요.

  • POST /stations/{id}/os/halt — 그 순간부터 모든 기기가 명령을 받지 않고, virtual Device 시작이 409 OS_HALTED 예요. 돌던 virtual Device 를 모두 멈춰요(Storage 는 남아요). 비상 정지 버튼이에요.
  • POST /stations/{id}/os/boot — 다시 받기 시작해요. virtual Device 를 다시 켜지는 않아요 — 비용이 나가는 일은 사용자가 직접 켜요.

기기·저장 객체가 하나라도 남아 있으면 409 STATION_NOT_EMPTY (details 에 남은 수). 한꺼번에 지우는 경로는 없어요 — 되돌릴 수 없는 일이 숨지 않게요. Station 만들기·지우기는 사용자 JWT 로만 돼요.

프로젝트는 Station 을 묶는 단위예요. 이름과 설명만 있어요. 프로젝트 API 는 사용자 JWT 로만 돼요 (API 키면 403 FORBIDDEN).

할 일 경로
내 정보 GET /me — 로그인한 계정의 이름·이메일·사용자 이름과 프로젝트 수
목록 · 만들기 GET · POST /projects {name, description?} — 이름순. 사용자당 20개 (409 PROJECT_LIMIT_REACHED)
보기 · 바꾸기 · 지우기 GET · PATCH · DELETE /projects/{id} — Station 이 남아 있으면 못 지워요 (409 PROJECT_NOT_EMPTY, details.stations)
프로젝트의 Station GET /projects/{id}/stations
프로젝트의 API 키 GET /projects/{id}/api-keys — 키는 Station 단위예요. 발급·폐기는 Station 경로 그대로
감사 로그 GET /projects/{id}/audit-logs ?station_id=&user_id=&from=&to= · 계정 전체는 GET /audit-logs ?project_id=&station_id=&from=&to= — 최신순

없거나 남의 프로젝트는 404 PROJECT_NOT_FOUND 예요. 프로젝트를 만들어도 크레딧이 생기지는 않아요 — 크레딧은 계정 단위예요.

감사 로그에는 게이트웨이를 지난 쓰기 요청(POST·PUT·PATCH·DELETE)이 한 줄씩 남아요 — 누가(사용자·API 키), 무엇을(메서드·경로), 결과(HTTP 상태). 읽기는 남기지 않아요. 계정 전체의 감사 로그에는 프로젝트 밖의 쓰기(프로젝트 만들기·충전)도 들어 있어요.

크레딧은 endue OS 안의 유일한 화폐예요. 내 계정에 지갑이 하나 있고, 모든 프로젝트의 사용이 이 지갑에서 나가요. 빌링 API 는 사용자 JWT 로만 돼요.

쓰는 것 계산
명령 끝난 명령 1건마다
컴퓨트 virtual Device 가 running 인 분 × 크기(small·medium·large)별 단가
스토리지 virtual Device 가 있는 동안 GB × 시간

actual Device 는 명령만 써요 — 가만히 있는 기기에는 아무것도 계산하지 않아요. 단가는 GET /billing/rates 가 기준이에요 (지금 값은 가격 정책 전의 자리값이에요).

  • GET /billing/wallet — 잔액. 처음 쓸 때 지갑이 생기고 가입 크레딧이 들어와요 — 계정당 한 번이에요 (프로젝트마다 주지 않아요). 100 미만이면 low_balance: true.
  • GET /billing/ledger — 원장(grant·topup·usage·refund·adjustment). 추가만 하고 고치지 않아요.
  • GET /billing/usage — 기간의 사용 요약 (기본 최근 30일, metric 별·날짜별). ?project_id=·?station_id= 로 좁혀요.

잔액이 0 이하면 비용을 만드는 동작 — 명령, virtual Device 만들기·시작·재시작, 앱 열기 — 이 402 INSUFFICIENT_CREDITS 예요 (details.balance). 잔액이 음수가 되면 내 계정의 돌던 virtual Device 도 멈춰요. 이미 끝난 일을 되돌리지는 않아요.

터미널 창
curl -s $OS/api/v1/billing/packages -H "Authorization: Bearer $TOKEN" | jq '.data[] | {package_id, credits, price, currency}'
curl -s -X POST $OS/api/v1/billing/checkouts \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"package_id":"…"}' | jq '.data | {checkout_id, status, checkout_url}'

체크아웃을 만들고, checkout_url 의 결제 화면에서 끝내면 원장에 topup 이 한 번 붙어요.

프로젝트·Station·기기·API 키·빌링·사용량·감사 로그·모니터링·스토리지를 다루는 관리 화면을 console.endueos.com 으로 준비하고 있어요. 위의 API 를 그대로 써요. 데스크톱(사용자의 OS 화면)과는 따로예요.