15 KiB
15 KiB
| name | version | description |
|---|---|---|
| openai-usage-token-issue | 1.0.6 | OpenAI-compatible 사용자 추가와 usage metering용 IOP token을 발급하고 private Edge mapping, local secret store, 사용자가 승인한 Confluence metadata table을 동기화하는 운영 절차 |
openai-usage-token-issue
목적
OpenAI-compatible 사용량 metering에 쓸 IOP bearer token을 발급하고, raw token 없이 token_ref, token hash, principal_ref, 내부 alias 매핑만 운영 기록에 남긴다.
IOP는 사용자/테넌트 source of truth를 소유하지 않고, 외부 principal id 또는 내부 운영 id를 참조값으로만 다룬다.
이 스킬은 dev-corp에서 사용자 추가와 token 발급을 함께 요청받았을 때의 단일 진입점이다.
언제 호출할지
- OpenAI-compatible 호출 사용량을 특정
principal_ref또는 내부 alias로 귀속할 IOP token을 새로 발급할 때 - dev/dev-corp 운영자가 Grafana 사용량 label에 노출될
token_ref,principal_alias를 준비할 때 - raw bearer token을 tracked 파일이나 최종 보고에 남기지 않고 1회 전달해야 할 때
- dev-corp 사용자 추가와 함께 해당 사용자의 IOP token 발급·private Edge mapping 반영을 요청받았을 때
입력
operation: 사용자 추가와 함께 발급할 때는create를 사용한다. token만 추가하거나 회전할 때는 작업 의도를 명시한다. (기본:create)env: 대상 환경. 사용자 추가 발급 기본값은dev-corp이다. (기본:dev-corp)principal_ref: 외부 사용자/테넌트 프로젝트 또는 운영 시스템의 principal 참조값 (필수)principal_alias: Grafana에 노출할 내부 alias. 없으면principal_ref에서 secret이 아닌 짧은 별칭을 정한다. (선택)token_ref: metric label과 설정에 쓸 안정 token 참조값. 한principal_ref가 여러 앱/통합을 운영하면 앱/통합/용도별로 서로 다른token_ref를 발급한다. 없으면 token hash prefix로 만든다. (선택)output_path: raw token을 보관해야 한다면 이 프로젝트 repo root의 gitignoredtoken/.dev-corp-iop-token을 사용한다. 이 파일 외의 운영 기록은 raw token 없이 남긴다. (선택)
이 프로젝트의 local secret store
token/.dev-corp-iop-token은 repo root의 operator-local 파일이며, 한 줄에<private-user-key>: <raw-token>을 기록한다. 기본private-user-key는 요청자가 지정한 식별자다.- 발급 전에
.gitignore에 정확한/token/항목이 있는지 확인하고, 없으면 token directory 경로만 추가한다. raw token이나 사용자 값 자체를.gitignore에 쓰지 않는다. - 파일은
umask 077으로 만들거나 유지해 mode0600이어야 한다. 기존 기록을 보존하기 위해token/안의 후보 파일을 만든 뒤 검증하고 원자적으로 교체한다. - 요청자가 이메일을 private-user-key 또는 dev-corp
principal_ref로 명시하면, 그 이메일은 이 ignored local store와 private Edge 설정에만 둔다. tracked 파일, 스킬 예시, 최종 보고에는 실제 이메일을 쓰지 않는다.
승인된 Confluence metadata table 동기화
- 사용자가 사용자별 발급 현황을 특정 Confluence path에 표로 동기화하라고 명시했을 때만 target URL을 ignored operator-local 파일
token/.dev-corp-iop-confluence-target에 한 줄로 보관한다. 이 파일도 mode0600, ignored, untracked여야 하며, tracked 스킬·문서·최종 보고에는 draft share URL 또는 식별자를 쓰지 않는다. - Confluence 갱신 전에는 local secret store의 private-user-key 집합과 active
openai.principal_tokens[]의principal_ref집합을 1:1로 대조한다. local store에 없는 service/smoke principal은 표에서 제외하며, 불일치 또는 중복이면 표를 쓰지 않고 불일치를 보고한다. - 표의 source of truth는 local secret store의 private-user-key와 active Edge의
principal_ref,principal_alias,token_ref, 활성 상태다. 표는사용자,principal alias,token ref,상태,동기화 시각열만 사용하고 행은principal_ref로 upsert한다. raw token, token hash, Authorization 값, provider credential은 storage body와 API payload에 넣지 않는다. - 실제 갱신은
lgucorp-confluence-docs스킬의sync-token-metadata-table절차를 따른다. HTTP Basic 인증과 table JSON payload는 stdin 또는 동등한 비노출 stream으로 전달하며 raw token을 shell 인자 또는 payload에 넣지 않는다. - target draft/page는 id, title, status, version, parent, storage body를 먼저 읽는다. body가 비어 있으면 관리 섹션과 표를 쓰고, 비어 있지 않은 body는
IOP 사용자 토큰 발급 현황관리 섹션만 교체한다. - Confluence write 뒤에는 같은 content id를 다시 읽어 title·status·version·parent와 metadata 행 수·사용자/alias/ref/status 값을 active mapping과 내부 비교한다. 인증·권한·version conflict·재조회 실패 시 raw token store나 Edge mapping을 변경하거나 write를 자동 재시도하지 않는다.
사용자 추가(create) 기준
- 요청자가 이메일을 명시하면 그 값은 private-user-key와 dev-corp
principal_ref로만 사용한다. tracked 문서·스킬 예시·최종 보고에는 실제 값을 쓰지 않는다. principal_alias는 요청자 식별에 쓸 짧은 ASCII alias로 정하고,token_ref는iop-dev-corp-<alias>처럼 환경과 용도를 포함한 안정값으로 정한다.- active private Edge config에서 같은
principal_ref또는token_ref를 먼저 찾는다. 하나라도 있으면 새 raw token을 발급하지 않고 기존 매핑의 활성 상태를 확인한다. operation=create은iop-user-crud-ops의 create 책임과 함께 적용하되, raw token 생성·local secret store·principal token 매핑 절차는 이 스킬이 소유한다.
먼저 확인할 것
principal_ref가 secret, provider token, provider identity가 아니라 외부 시스템 참조값인지 확인한다. 운영자가 private dev-corp 매핑의 이메일을 명시한 경우에는 ignored local store와 private Edge 설정으로 범위를 제한한다.- raw token을 tracked
docs/,agent-roadmap/,agent-spec/,configs/, git diff, shell history, 최종 보고에 남기지 않을 전달 경로를 정한다. - raw token 보관이 필요한 경우
token/.dev-corp-iop-token의 ignore 상태와 mode0600을 확인한다. - Confluence 동기화를 요청받은 경우
token/.dev-corp-iop-confluence-target의 mode0600, ignored, untracked 상태와 대상 page 접근을 확인한다. token_ref와principal_alias가 낮은 cardinality label로 안전한 값인지 확인한다.- 같은
principal_ref에 여러 앱/통합용 token이 필요한 경우 각 token의 앱/통합/용도 구분이token_ref에 반영되는지 확인한다. - 기존 token을 회전하는 경우 기존
token_ref를 재사용할지 새token_ref를 만들지 운영 정책을 확인한다.
실행 절차
-
입력 정규화
principal_ref앞뒤 공백을 제거한다.principal_alias는 공백을-로 바꾸고, 운영자가 식별할 수 있는 짧은 ASCII alias로 둔다.token_ref를 직접 받지 않았으면 생성할 token hash의 앞 16자를 사용해ioptok_<hash-prefix>형식으로 만든다.operation=create이면 raw token 생성 전에 active private Edge config의principal_ref와token_ref중복을 확인한다. 기존 매핑이 있으면 발급을 중단하고 활성 상태를 검증한다.
-
raw token 생성
- 현재 shell에서
set +x를 확인한다. - 아래 형태의 고엔트로피 token을 생성한다. 실제 출력은 operator에게 1회만 전달한다.
- 현재 shell에서
set +x
umask 077
raw_token="iop_$(openssl rand -base64 36 | tr '+/' '-_' | tr -d '=')"
token_hash="$(printf '%s' "$raw_token" | sha256sum | awk '{print $1}')"
token_ref="${token_ref:-ioptok_${token_hash:0:16}}"
-
local secret store 갱신
- raw token을 보관해야 할 때만 repo root의
token/.dev-corp-iop-token에<private-user-key>: <raw-token>한 줄을 추가한다. - 새 파일 또는 후보 파일은
umask 077으로 만들고, 기존 매핑을 보존한 뒤 mode0600및 ignore 상태를 검증한다. - raw token을 shell 인자, trace, 화면 출력, tracked diff에 노출하지 않는다.
- raw token을 보관해야 할 때만 repo root의
-
사용자 추가와 private Edge 후보 반영
operation=create이면 active private Edge config의openai.principal_tokens[]에서principal_ref와token_ref중복을 다시 확인한다.- local secret store는
token/안의 후보 파일에 기존 레코드와 새<private-user-key>: <raw-token>을 함께 기록하고, mode0600·ignore 상태를 확인한 뒤 원자적으로 교체한다. - raw token은 SSH 표준 입력처럼 비노출 stream으로만 private Edge config 후보 생성기에 전달한다. 후보 config에는
token_ref, SHA-256 hash,principal_ref,principal_alias만 기록한다. openai.principal_tokens[]변경은 restart-required다. 환경 배포 스킬의 config check·refresh dry-run·backup/mv cutover·Edge restart 절차를 따른다. live apply 완료로 처리하지 않는다.
-
raw-token-free 운영 기록 작성
- tracked 문서나 공유 운영 기록에는 아래 필드만 남긴다.
token_ref: "<token_ref>"
principal_ref: "<principal_ref>"
principal_alias: "<principal_alias>"
token_hash_sha256: "<token_hash>"
status: active
-
승인된 Confluence metadata table 동기화
- 동기화 요청이 있을 때만 local secret store의 private-user-key와 active Edge
principal_tokens[]를principal_ref기준으로 1:1 대조한다. 불일치 또는 중복이면 표를 쓰지 않고blocked로 보고한다. - target URL은
token/.dev-corp-iop-confluence-target에서만 읽고,lgucorp-confluence-docs의sync-token-metadata-table인증·대상 재조회·version 기반 update 절차를 사용한다. - 표에는
사용자,principal alias,token ref,상태: active,동기화 시각만 넣는다. raw token, token hash, Authorization 값, provider credential, draft share URL은 넣지 않는다. - target body가 비어 있으면 관리 섹션과 표를 쓰고, 비어 있지 않으면
IOP 사용자 토큰 발급 현황관리 섹션만 대체한다. 다른 섹션, title, parent, 권한은 변경하지 않는다. - 갱신 후 page 재조회로 table의 행 수·사용자/alias/ref/status metadata를 active mapping과 내부 검증한다. 실패하면 결과를
blocked로 보고하고, 앞선 token/Edge 상태를 되돌리거나 새 token을 발급하지 않는다.
- 동기화 요청이 있을 때만 local secret store의 private-user-key와 active Edge
-
raw token 1회 전달
- raw token은 operator-only 채널로 한 번만 전달한다.
- 채팅 최종 보고, git diff, tracked 문서, 검증 출력에는 raw token을 쓰지 않는다.
-
누출 확인
- 저장소 안에 raw token이 남지 않았는지 조용한 검색으로 확인한다. 실패 시 출력에 raw token이 찍히지 않게 한다.
- 검사 대상에서 의도된 ignored
token/directory는 제외하되, 그 안의 secret store가 추적되지 않았음을 별도로 확인한다.
if rg -q -F "$raw_token" agent-ops agent-roadmap agent-spec agent-contract docs configs apps packages proto; then
echo "raw token leak detected in tracked workspace paths"
exit 1
fi
echo "raw token not found in tracked workspace paths"
- 결과 보고
token_ref,principal_ref,principal_alias, 매핑 기록 위치, Confluence metadata table 동기화 상태, raw token 전달 여부만 보고한다.- raw token과 전체 token hash는 보고하지 않는다.
실행 결과 검증
operation=create의 active private Edge config에 대상principal_ref와token_ref가 각각 한 번만 존재하는가- raw token이 operator에게 1회만 전달되었는가
- tracked 파일에는 raw token이 없고,
token_ref,principal_ref,principal_alias, hash만 남았는가 token/.dev-corp-iop-token이 mode0600이고git check-ignore -q token/.dev-corp-iop-token을 통과하며git ls-files --error-unmatch token/.dev-corp-iop-token이 실패하는가- Confluence 동기화를 요청한 경우
token/.dev-corp-iop-confluence-target이 mode0600, ignored, untracked이고, local private-user-key 집합과 active Edgeprincipal_ref집합이 일치하는가 - Confluence table은 local secret store의 각 사용자당 정확히 한 행이고
사용자, alias, ref, status metadata가 active mapping과 일치하며 raw token·token hash를 포함하지 않는가 - Confluence 갱신 뒤 같은 draft/page의 title, status, parent가 유지되고 version·table 행 수가 기대값으로 재조회되는가
- Edge restart 후 새 token으로
/v1/models와/v1/chat/completions인증이 성공하고, 가능한 경우 usage metric의 principal/token label이 관측되는가 rg -q -F "$raw_token" ...누출 확인이 실패하지 않았는가- 최종 보고에 raw token, provider token, provider identity, raw prompt/response가 포함되지 않았는가
- 검증 실패 시: raw token을 폐기하고 새 token을 발급한다. 누출된 tracked 파일은 수정한 뒤 다시 누출 확인을 실행하고, local secret store는 새 후보 파일 검증 뒤에만 교체한다.
출력 형식
OpenAI usage token issue
- operation: <create|rotate-token|other>
- token_ref: <token_ref>
- principal_ref: <principal_ref>
- principal_alias: <principal_alias>
- secret_store: token/.dev-corp-iop-token
- edge_mapping: <candidate-validated-and-restarted|existing-verified|not-applied>
- confluence_metadata_sync: <updated|not-requested|blocked>
- mapping_record: <path or operator-private store>
- raw_token_delivered_once: <yes|no>
- leak_check: <pass|fail>
- notes: raw token omitted from report
금지 사항
- raw token을 tracked 파일, 최종 보고, 로그, metric label, Grafana dashboard, shell trace에 남기지 않는다.
- raw token 또는 실제 요청자 식별자를
.gitignore, 스킬 예시, tracked 문서, shell 인자에 쓰지 않는다..gitignore에는/token/directory 경로만 둔다. - raw token, token hash, Authorization 값, provider credential, draft share URL을 Confluence metadata table 또는 Confluence API payload에 넣지 않는다.
- local secret store와 active Edge mapping이 1:1로 대조되지 않은 상태에서 Confluence 표를 갱신하거나, 관리 섹션 밖의 본문·title·parent를 변경하지 않는다.
- active config에 같은
principal_ref또는token_ref가 있는데 새 raw token을 발급하거나 중복 entry를 추가하지 않는다. metadata.user, provider token, provider identity를 사용자 식별 source로 쓰지 않는다.request_id,session_id, raw token, raw prompt, raw response 같은 high-cardinality 또는 secret 값을 metric label 후보로 만들지 않는다.- 사용자 CRUD, tenant/org source of truth, token 제한 enforcement를 이 스킬 책임으로 확장하지 않는다.