Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
21 lines
1.2 KiB
JavaScript
21 lines
1.2 KiB
JavaScript
/**
|
|
* portal/commerce/opsauth.mjs — 운영자 콘솔(HAL)에서 들어오는 내부 호출(/internal/ops/*) 인증.
|
|
*
|
|
* 운영자 계정·세션은 HAL 에 있고(§25), HAL 이 포털의 내부 API 를 서비스 키로 호출한다(lib/serviceauth).
|
|
* 비밀은 포털 보관소의 'service:<keyId>' 에 있다. 허용 키 id 는 'hal' 뿐이다.
|
|
* 호출 주체 운영자 식별(감사 기록용)은 HAL 이 X-Ops-Actor 헤더로 전달한다(이름만, 비밀 없음).
|
|
* 테스트에서는 deps.opsAuthBypass=true 로 서명 없이 부를 수 있다(운영 코드 경로에서는 절대 켜지 않는다).
|
|
*/
|
|
import { HttpError } from '../../lib/http.mjs';
|
|
import { verifyCtx } from '../../lib/serviceauth.mjs';
|
|
|
|
const ALLOWED_KEYS = new Set(['hal']);
|
|
/** 검증 후 { keyId, actor } 를 돌려준다. 실패는 401. */
|
|
export async function requireOps(ctx, deps) {
|
|
const actor = String(ctx.headers['x-ops-actor'] || 'operator').slice(0, 80);
|
|
if (deps.opsAuthBypass) return { keyId: 'test', actor };
|
|
const r = await verifyCtx(ctx, (id) => (ALLOWED_KEYS.has(id) ? deps.vault.get('service:' + id) : null));
|
|
if (!r.ok) throw new HttpError(401, 'service_auth_failed', `운영자 콘솔 호출 인증 실패(${r.reason})`);
|
|
return { keyId: r.keyId, actor };
|
|
}
|