/** * Google OAuth "권한 도메인" → 스코프 매핑의 SSOT. * * mimi-seed 는 통합 플랫폼이라 여러 구글 서비스 스코프를 다루는데, 예전엔 로그인 한 번에 * 전부(full-scope)를 강제로 요청했다. OAuth 앱 심사(verification)의 "Requesting Minimum * Scopes" 요건과 least-privilege 원칙에 맞추기 위해, 사용자가 쓸 도메인만 골라 동의하는 * 선택형(incremental) 인증으로 바꿨다: * * - 로그인 시 도메인 서브셋만 요청 가능 (`mimi-seed-auth --domains ga4,googleads`, * MCP `mimi_seed_auth_start` 의 `domains` 파라미터). 미지정 시 기존과 동일한 전체 요청. * - `include_granted_scopes=true` 로 요청하므로, 나중에 도메인을 추가해도 기존 부여 * 권한은 유지된 채 새 권한만 얹힌다 (Google incremental authorization). * - 도구 쪽은 `requireAuth()` pre-flight 가 미부여 도메인을 결정적으로 안내한다. * * 도메인 경계는 "어느 도구 군이 어느 스코프를 실제 소비하는가" 기준이다. 특히 * cloud-platform 은 IAM API(서비스 계정 생성·키 발급)가 더 좁은 대안 스코프를 제공하지 * 않아서 유지하되, `gcp` 도메인으로 격리해 그 도구를 쓰는 사용자만 요청하게 한다. */ export interface AuthDomainDef { /** 사람이 읽을 라벨 (동의 화면 아님 — CLI/도구 안내용) */ label: string; scopes: readonly string[]; /** 이 도메인이 여는 도구/작업 요약 — CLI·MCP 안내 문자열에 사용 */ summary: string; } export declare const AUTH_DOMAINS: { readonly firebase: { readonly label: "Firebase"; readonly scopes: readonly ["https://www.googleapis.com/auth/firebase"]; readonly summary: "firebase_* — 프로젝트/앱/설정 조회·생성 (프로젝트 신규 생성·서비스 활성화는 gcp 도 필요)"; }; readonly gcp: { readonly label: "Google Cloud (cloud-platform)"; readonly scopes: readonly ["https://www.googleapis.com/auth/cloud-platform"]; readonly summary: "iam_* (서비스 계정·키·IAM 바인딩 — IAM API 는 이 스코프의 좁은 대안이 없음), firebase 프로젝트 생성·서비스 활성화, BigQuery OAuth fallback"; }; readonly admob: { readonly label: "AdMob"; readonly scopes: readonly ["https://www.googleapis.com/auth/admob.readonly", "https://www.googleapis.com/auth/admob.monetization"]; readonly summary: "admob_* — 수익 리포트, 앱·광고 단위 생성"; }; readonly playstore: { readonly label: "Play Store"; readonly scopes: readonly ["https://www.googleapis.com/auth/androidpublisher", "https://www.googleapis.com/auth/playdeveloperreporting"]; readonly summary: "playstore_* — OAuth 로 하는 Play Console 작업 + Android vitals 통계"; }; readonly googleads: { readonly label: "Google Ads"; readonly scopes: readonly ["https://www.googleapis.com/auth/adwords"]; readonly summary: "googleads_* — 캠페인·UAC 리포트"; }; readonly gsc: { readonly label: "Search Console"; readonly scopes: readonly ["https://www.googleapis.com/auth/webmasters"]; readonly summary: "gsc_* — 사이트·사이트맵·검색 성과 (사이트맵 제출 포함)"; }; readonly ga4: { readonly label: "Google Analytics (GA4)"; readonly scopes: readonly ["https://www.googleapis.com/auth/analytics.edit", "https://www.googleapis.com/auth/analytics.readonly"]; readonly summary: "ga4_* — property/data stream 생성·조회 + 리포트"; }; readonly youtube: { readonly label: "YouTube"; readonly scopes: readonly ["https://www.googleapis.com/auth/youtube.force-ssl"]; readonly summary: "youtube_* — 영상 업로드·처리 상태 조회·공개 상태 변경"; }; }; export type AuthDomainId = keyof typeof AUTH_DOMAINS; /** z.enum 등 튜플이 필요한 자리에 쓰는 도메인 id 목록 (선언 순서 유지). */ export declare const DOMAIN_IDS: [AuthDomainId, ...AuthDomainId[]]; export declare const CLOUD_PLATFORM_SCOPE: "https://www.googleapis.com/auth/cloud-platform"; /** * Play Developer Reporting API(Android vitals 통계) 전용 스코프. androidpublisher 와 * 별개다 — SA JWT 와 OAuth playstore 도메인 양쪽에 함께 실어야 통계 도구가 동작한다. * * CLOUD_PLATFORM_SCOPE 처럼 도메인 정의에서 **파생**한다(리터럴을 두 번 적지 않는다). * 별도 리터럴로 두면 도메인 배열과 어긋나도 어떤 테스트도 못 잡고, SA(const 사용)와 * OAuth pre-flight(도메인 리터럴)가 다른 문자열을 봐 정상 로그인이 INSUFFICIENT_SCOPE 로 * 죽는 함정이 된다. auth-scopes.test.ts 가 값과 도메인 포함 여부를 함께 고정한다. */ export declare const PLAY_DEVELOPER_REPORTING_SCOPE: "https://www.googleapis.com/auth/playdeveloperreporting"; /** * 공백 구분 scope 문자열들의 합집합. tokens.json 의 scope 는 누적(monotonic)이어야 하므로 * 로그인/갱신 시 기존 기록 + 새 응답을 합쳐 저장하는 데 쓴다. undefined/빈 문자열은 무시. */ export declare function mergeScopeStrings(...parts: Array): string; /** * 전체 스코프 (도메인 선언 순서대로 평탄화). * 도메인 미지정 로그인의 기본값이자, 선택형 도입 전 full-scope 목록과 동일해야 한다 * (auth-scopes.test.ts 가 고정한다 — 스코프가 소리 없이 빠지면 기존 사용자 도구가 죽는다). */ export declare const ALL_SCOPES: readonly string[]; /** 도메인 서브셋 → 요청할 스코프 목록. 미지정/빈 배열이면 전체(기존 동작). */ export declare function scopesForDomains(domains?: readonly AuthDomainId[]): string[]; /** 스코프 하나를 요구하는 도메인들 (INSUFFICIENT_SCOPE 안내에서 "--domains X" 를 채울 때 사용). */ export declare function domainsForScope(scope: string): AuthDomainId[]; /** CLI `--domains a,b,c` 파싱. 잘못된 id 는 invalid 로 분리해 호출자가 안내한다. */ export declare function parseDomainList(raw: string): { domains: AuthDomainId[]; invalid: string[]; }; export interface GrantedDomainSummary { /** tokens.json 에 scope 기록이 있는지. false 면 스코프 추적 도입 전 구 토큰. */ known: boolean; /** 도메인의 스코프가 전부 부여된 도메인들 */ granted: AuthDomainId[]; /** 하나라도 미부여인 도메인들 */ missing: AuthDomainId[]; } /** tokens.json 의 공백 구분 scope 문자열 → 도메인 단위 부여 현황. */ export declare function summarizeGrantedDomains(scopeStr: string | undefined): GrantedDomainSummary; /** 구 토큰(scope 미기록)이 이 스코프를 보유했다고 간주해도 되는가. */ export declare function isPreTrackingScope(scope: string): boolean;