feat: complete release preparation, 10+ ad mediation, CI/CD, and docker deployment
Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped
Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped
This commit is contained in:
parent
5cd1de6859
commit
708e20f747
406 changed files with 42464 additions and 6199 deletions
114
apps/desktop/tests/red/crypto-license.usecase.test.ts
Normal file
114
apps/desktop/tests/red/crypto-license.usecase.test.ts
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
// apps/desktop/tests/red/crypto-license.usecase.test.ts
|
||||
// Phase 11+: Ed25519 비대칭 암호화 라이센스 검증 & Reverse Trial 유스케이스 테스트
|
||||
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import {
|
||||
generateLicenseKeyPair,
|
||||
issueSignedLicenseKey,
|
||||
verifySignedLicenseKey,
|
||||
createDefaultTrialPayload,
|
||||
DEFAULT_LICENSE_PUBLIC_KEY,
|
||||
} from '@d3ro/core/utils/crypto-license'
|
||||
import { getLicenseService } from '../../src/main/services/LicenseService'
|
||||
import { useRedHarness } from './harness'
|
||||
|
||||
useRedHarness()
|
||||
|
||||
describe('Ed25519 암호화 라이센스 & Reverse Trial 유스케이스', () => {
|
||||
it('Ed25519 키쌍을 생성하고 유효한 라이센스를 서명/검증할 수 있다', () => {
|
||||
const { publicKeyPem, privateKeyPem } = generateLicenseKeyPair()
|
||||
expect(publicKeyPem).toContain('BEGIN PUBLIC KEY')
|
||||
expect(privateKeyPem).toContain('BEGIN PRIVATE KEY')
|
||||
|
||||
const payload = {
|
||||
licenseId: 'lic-1001',
|
||||
tier: 'pro_plus' as const,
|
||||
customerEmail: 'alice@enterprise.com',
|
||||
issuedAt: Date.now(),
|
||||
expiresAt: Date.now() + 365 * 24 * 60 * 60 * 1000,
|
||||
machineId: 'test-machine-id-1234',
|
||||
}
|
||||
|
||||
const key = issueSignedLicenseKey(payload, privateKeyPem)
|
||||
expect(key.startsWith('D3RO-LIC-')).toBe(true)
|
||||
|
||||
// 검증 성공
|
||||
const verification = verifySignedLicenseKey(key, 'test-machine-id-1234', publicKeyPem)
|
||||
expect(verification.valid).toBe(true)
|
||||
expect(verification.tier).toBe('pro_plus')
|
||||
expect(verification.reason).toBe('valid')
|
||||
expect(verification.payload?.customerEmail).toBe('alice@enterprise.com')
|
||||
})
|
||||
|
||||
it('머신 ID가 일치하지 않으면 machine_mismatch 로 실패한다', () => {
|
||||
const { publicKeyPem, privateKeyPem } = generateLicenseKeyPair()
|
||||
const payload = {
|
||||
licenseId: 'lic-1002',
|
||||
tier: 'pro' as const,
|
||||
customerEmail: 'bob@company.com',
|
||||
issuedAt: Date.now(),
|
||||
expiresAt: null,
|
||||
machineId: 'machine-A',
|
||||
}
|
||||
|
||||
const key = issueSignedLicenseKey(payload, privateKeyPem)
|
||||
const verification = verifySignedLicenseKey(key, 'machine-B', publicKeyPem)
|
||||
expect(verification.valid).toBe(false)
|
||||
expect(verification.reason).toBe('machine_mismatch')
|
||||
})
|
||||
|
||||
it('만료된 라이센스는 expired 로 실패한다', () => {
|
||||
const { publicKeyPem, privateKeyPem } = generateLicenseKeyPair()
|
||||
const payload = {
|
||||
licenseId: 'lic-1003',
|
||||
tier: 'pro' as const,
|
||||
customerEmail: 'charlie@past.com',
|
||||
issuedAt: Date.now() - 100000,
|
||||
expiresAt: Date.now() - 1000, // 이미 만료됨
|
||||
machineId: null,
|
||||
}
|
||||
|
||||
const key = issueSignedLicenseKey(payload, privateKeyPem)
|
||||
const verification = verifySignedLicenseKey(key, undefined, publicKeyPem)
|
||||
expect(verification.valid).toBe(false)
|
||||
expect(verification.reason).toBe('expired')
|
||||
})
|
||||
|
||||
it('서명이 위조된 라이센스는 invalid_signature 로 실패한다', () => {
|
||||
const { publicKeyPem } = generateLicenseKeyPair()
|
||||
const otherKeyPair = generateLicenseKeyPair()
|
||||
|
||||
const payload = {
|
||||
licenseId: 'lic-forged',
|
||||
tier: 'pro_plus' as const,
|
||||
customerEmail: 'attacker@evil.com',
|
||||
issuedAt: Date.now(),
|
||||
expiresAt: null,
|
||||
machineId: null,
|
||||
}
|
||||
|
||||
// 다른 키로 서명 (위조 시도)
|
||||
const forgedKey = issueSignedLicenseKey(payload, otherKeyPair.privateKeyPem)
|
||||
const verification = verifySignedLicenseKey(forgedKey, undefined, publicKeyPem)
|
||||
expect(verification.valid).toBe(false)
|
||||
expect(verification.reason).toBe('invalid_signature')
|
||||
})
|
||||
|
||||
it('LicenseService.startTrial() 호출 시 14일 Pro+ Reverse Trial 이 활성화된다', () => {
|
||||
const svc = getLicenseService()
|
||||
svc.initialize()
|
||||
|
||||
const result = svc.startTrial('trial-tester@local')
|
||||
expect(result.success).toBe(true)
|
||||
expect(result.tier).toBe('pro_plus')
|
||||
expect(svc.tier).toBe('pro_plus')
|
||||
|
||||
const info = svc.getInfo()
|
||||
expect(info.isTrial).toBe(true)
|
||||
expect(info.trialExpiresAt).toBeGreaterThan(Date.now())
|
||||
|
||||
// 중복 체험 시작은 방지된다
|
||||
const retry = svc.startTrial('again@local')
|
||||
expect(retry.success).toBe(false)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue